e3a31276f0404d27feba3e5b83ae5207100d7fdd
[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 "CFDictionaryPropertyBag.h"\r
33 #include "COMEnumVariant.h"\r
34 #include "MarshallingHelpers.h"\r
35 #include "WebNotificationCenter.h"\r
36 #include "WebSecurityOrigin.h"\r
37 \r
38 #include <WebCore/BString.h>\r
39 #include <WebCore/COMPtr.h>\r
40 #include <WebCore/DatabaseTracker.h>\r
41 #include <WebCore/FileSystem.h>\r
42 #include <WebCore/SecurityOrigin.h>\r
43 \r
44 using namespace WebCore;\r
45 \r
46 static inline bool isEqual(LPCWSTR s1, LPCWSTR s2)\r
47 {\r
48     return !wcscmp(s1, s2);\r
49 }\r
50 \r
51 class DatabaseDetailsPropertyBag : public IPropertyBag, Noncopyable {\r
52 public:\r
53     static DatabaseDetailsPropertyBag* createInstance(const DatabaseDetails&);\r
54 \r
55     // IUnknown\r
56     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);\r
57     virtual ULONG STDMETHODCALLTYPE AddRef();\r
58     virtual ULONG STDMETHODCALLTYPE Release();\r
59 \r
60     // IPropertyBag\r
61     virtual HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog);\r
62     virtual HRESULT STDMETHODCALLTYPE Write(LPCOLESTR pszPropName, VARIANT* pVar);\r
63 private:\r
64     DatabaseDetailsPropertyBag(const DatabaseDetails& details) \r
65         : m_refCount(0)\r
66         , m_details(details) { }\r
67     ~DatabaseDetailsPropertyBag() { }\r
68 \r
69     ULONG m_refCount;\r
70     DatabaseDetails m_details;\r
71 };\r
72 \r
73 // DatabaseDetailsPropertyBag ------------------------------------------------------\r
74 DatabaseDetailsPropertyBag* DatabaseDetailsPropertyBag::createInstance(const DatabaseDetails& details)\r
75 {\r
76     DatabaseDetailsPropertyBag* instance = new DatabaseDetailsPropertyBag(details);\r
77     instance->AddRef();\r
78     return instance;\r
79 }\r
80 \r
81 // IUnknown ------------------------------------------------------------------------\r
82 ULONG STDMETHODCALLTYPE DatabaseDetailsPropertyBag::AddRef()\r
83 {\r
84     return ++m_refCount;\r
85 }\r
86 \r
87 ULONG STDMETHODCALLTYPE DatabaseDetailsPropertyBag::Release()\r
88 {\r
89     ULONG newRef = --m_refCount;\r
90     if (!newRef)\r
91         delete this;\r
92 \r
93     return newRef;\r
94 }\r
95 \r
96 HRESULT STDMETHODCALLTYPE DatabaseDetailsPropertyBag::QueryInterface(REFIID riid, void** ppvObject)\r
97 {\r
98     *ppvObject = 0;\r
99     if (IsEqualGUID(riid, IID_IUnknown))\r
100         *ppvObject = static_cast<DatabaseDetailsPropertyBag*>(this);\r
101     else if (IsEqualGUID(riid, IID_IPropertyBag))\r
102         *ppvObject = static_cast<DatabaseDetailsPropertyBag*>(this);\r
103     else\r
104         return E_NOINTERFACE;\r
105 \r
106     AddRef();\r
107     return S_OK;\r
108 }\r
109 \r
110 // IPropertyBag --------------------------------------------------------------------\r
111 HRESULT STDMETHODCALLTYPE DatabaseDetailsPropertyBag::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog*)\r
112 {\r
113     if (!pszPropName || !pVar)\r
114         return E_POINTER;\r
115 \r
116     VariantInit(pVar);\r
117 \r
118     if (isEqual(pszPropName, WebDatabaseDisplayNameKey)) {\r
119         COMVariantSetter<String>::setVariant(pVar, m_details.displayName());\r
120         return S_OK;\r
121     } else if (isEqual(pszPropName, WebDatabaseExpectedSizeKey)) {\r
122         COMVariantSetter<unsigned long long>::setVariant(pVar, m_details.expectedUsage());\r
123         return S_OK;\r
124     } else if (isEqual(pszPropName, WebDatabaseUsageKey)) {\r
125         COMVariantSetter<unsigned long long>::setVariant(pVar, m_details.currentUsage());\r
126         return S_OK;\r
127     }\r
128 \r
129     return E_INVALIDARG;\r
130 }\r
131 \r
132 HRESULT STDMETHODCALLTYPE DatabaseDetailsPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar)\r
133 {\r
134     if (!pszPropName || !pVar)\r
135         return E_POINTER;\r
136 \r
137     return E_FAIL;\r
138 }\r
139 \r
140 static COMPtr<WebDatabaseManager> s_sharedWebDatabaseManager;\r
141 \r
142 // WebDatabaseManager --------------------------------------------------------------\r
143 WebDatabaseManager* WebDatabaseManager::createInstance()\r
144 {\r
145     WebDatabaseManager* manager = new WebDatabaseManager();\r
146     manager->AddRef();\r
147     return manager;    \r
148 }\r
149 \r
150 WebDatabaseManager::WebDatabaseManager()\r
151     : m_refCount(0)\r
152 {\r
153     gClassCount++;\r
154 }\r
155 \r
156 WebDatabaseManager::~WebDatabaseManager()\r
157 {\r
158     gClassCount--;\r
159 }\r
160 \r
161 // IUnknown ------------------------------------------------------------------------\r
162 HRESULT STDMETHODCALLTYPE WebDatabaseManager::QueryInterface(REFIID riid, void** ppvObject)\r
163 {\r
164     *ppvObject = 0;\r
165     if (IsEqualGUID(riid, IID_IUnknown))\r
166         *ppvObject = static_cast<WebDatabaseManager*>(this);\r
167     else if (IsEqualGUID(riid, IID_IWebDatabaseManager))\r
168         *ppvObject = static_cast<WebDatabaseManager*>(this);\r
169     else\r
170         return E_NOINTERFACE;\r
171 \r
172     AddRef();\r
173     return S_OK;\r
174 }\r
175 \r
176 ULONG STDMETHODCALLTYPE WebDatabaseManager::AddRef()\r
177 {\r
178     return ++m_refCount;\r
179 }\r
180 \r
181 ULONG STDMETHODCALLTYPE WebDatabaseManager::Release()\r
182 {\r
183     ULONG newRef = --m_refCount;\r
184     if (!newRef)\r
185         delete this;\r
186 \r
187     return newRef;\r
188 }\r
189 \r
190 template<> struct COMVariantSetter<RefPtr<SecurityOrigin> > : COMIUnknownVariantSetter<WebSecurityOrigin, RefPtr<SecurityOrigin> > {};\r
191 \r
192 // IWebDatabaseManager -------------------------------------------------------------\r
193 HRESULT STDMETHODCALLTYPE WebDatabaseManager::sharedWebDatabaseManager( \r
194     /* [retval][out] */ IWebDatabaseManager** result)\r
195 {\r
196     if (!s_sharedWebDatabaseManager) {\r
197         s_sharedWebDatabaseManager.adoptRef(WebDatabaseManager::createInstance());\r
198         DatabaseTracker::tracker().setClient(s_sharedWebDatabaseManager.get());\r
199     }\r
200 \r
201     return s_sharedWebDatabaseManager.copyRefTo(result);\r
202 }\r
203 \r
204 HRESULT STDMETHODCALLTYPE WebDatabaseManager::origins( \r
205     /* [retval][out] */ IEnumVARIANT** result)\r
206 {\r
207     if (!result)\r
208         return E_POINTER;\r
209 \r
210     *result = 0;\r
211 \r
212     if (this != s_sharedWebDatabaseManager)\r
213         return E_FAIL;\r
214 \r
215     Vector<RefPtr<SecurityOrigin> > origins;\r
216     DatabaseTracker::tracker().origins(origins);\r
217         COMPtr<COMEnumVariant<Vector<RefPtr<SecurityOrigin> > > > enumVariant(AdoptCOM, COMEnumVariant<Vector<RefPtr<SecurityOrigin> > >::adopt(origins));\r
218 \r
219     *result = enumVariant.releaseRef();\r
220     return S_OK;\r
221 }\r
222     \r
223 HRESULT STDMETHODCALLTYPE WebDatabaseManager::databasesWithOrigin( \r
224     /* [in] */ IWebSecurityOrigin* origin,\r
225     /* [retval][out] */ IEnumVARIANT** result)\r
226 {\r
227     if (!origin || !result)\r
228         return E_POINTER;\r
229 \r
230     *result = 0;\r
231 \r
232     if (this != s_sharedWebDatabaseManager)\r
233         return E_FAIL;\r
234 \r
235     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
236     if (!webSecurityOrigin)\r
237         return E_FAIL;\r
238 \r
239     Vector<String> databaseNames;\r
240     DatabaseTracker::tracker().databaseNamesForOrigin(webSecurityOrigin->securityOrigin(), databaseNames);\r
241 \r
242     COMPtr<COMEnumVariant<Vector<String> > > enumVariant(AdoptCOM, COMEnumVariant<Vector<String> >::adopt(databaseNames));\r
243 \r
244     *result = enumVariant.releaseRef();\r
245     return S_OK;\r
246 }\r
247 \r
248 HRESULT STDMETHODCALLTYPE WebDatabaseManager::detailsForDatabaseWithOrigin( \r
249     /* [in] */ BSTR databaseName,\r
250     /* [in] */ IWebSecurityOrigin* origin,\r
251     /* [retval][out] */ IPropertyBag** result)\r
252 {\r
253     if (!origin || !result)\r
254         return E_POINTER;\r
255 \r
256     *result = 0;\r
257 \r
258     if (this != s_sharedWebDatabaseManager)\r
259         return E_FAIL;\r
260 \r
261     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
262     if (!webSecurityOrigin)\r
263         return E_FAIL;\r
264 \r
265     DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(String(databaseName, SysStringLen(databaseName)),\r
266         webSecurityOrigin->securityOrigin());\r
267 \r
268     if (!details.isValid())\r
269         return E_INVALIDARG;\r
270 \r
271     *result = DatabaseDetailsPropertyBag::createInstance(details);\r
272     return S_OK;\r
273 }\r
274     \r
275 HRESULT STDMETHODCALLTYPE WebDatabaseManager::deleteAllDatabases()\r
276 {\r
277     if (this != s_sharedWebDatabaseManager)\r
278         return E_FAIL;\r
279 \r
280     DatabaseTracker::tracker().deleteAllDatabases();\r
281 \r
282     return S_OK;\r
283 }\r
284    \r
285 HRESULT STDMETHODCALLTYPE WebDatabaseManager::deleteDatabasesWithOrigin( \r
286     /* [in] */ IWebSecurityOrigin* origin)\r
287 {\r
288     if (!origin)\r
289         return E_POINTER;\r
290 \r
291     if (this != s_sharedWebDatabaseManager)\r
292         return E_FAIL;\r
293 \r
294     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
295     if (!webSecurityOrigin)\r
296         return E_FAIL;\r
297 \r
298     DatabaseTracker::tracker().deleteDatabasesWithOrigin(webSecurityOrigin->securityOrigin());\r
299 \r
300     return S_OK;\r
301 }\r
302     \r
303 HRESULT STDMETHODCALLTYPE WebDatabaseManager::deleteDatabaseWithOrigin( \r
304     /* [in] */ BSTR databaseName,\r
305     /* [in] */ IWebSecurityOrigin* origin)\r
306 {\r
307     if (!origin)\r
308         return E_POINTER;\r
309 \r
310     if (!databaseName)\r
311         return E_INVALIDARG;\r
312 \r
313     if (this != s_sharedWebDatabaseManager)\r
314         return E_FAIL;\r
315 \r
316     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
317     if (!webSecurityOrigin)\r
318         return E_FAIL;\r
319 \r
320     DatabaseTracker::tracker().deleteDatabase(webSecurityOrigin->securityOrigin(), String(databaseName, SysStringLen(databaseName)));\r
321 \r
322     return S_OK;\r
323 }\r
324 \r
325 void WebDatabaseManager::dispatchDidModifyOrigin(SecurityOrigin* origin)
326 {
327     static BSTR databaseDidModifyOriginName = SysAllocString(WebDatabaseDidModifyOriginNotification);
328     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
329
330     COMPtr<WebSecurityOrigin> securityOrigin(AdoptCOM, WebSecurityOrigin::createInstance(origin));
331     notifyCenter->postNotificationName(databaseDidModifyOriginName, securityOrigin.get(), 0);
332 }
333
334 void WebDatabaseManager::dispatchDidModifyDatabase(SecurityOrigin* origin, const String& databaseName)
335 {
336     static BSTR databaseDidModifyOriginName = SysAllocString(WebDatabaseDidModifyDatabaseNotification);
337     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
338
339     COMPtr<WebSecurityOrigin> securityOrigin(AdoptCOM, WebSecurityOrigin::createInstance(origin));
340
341     RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
342
343     static CFStringRef databaseNameKey = MarshallingHelpers::LPCOLESTRToCFStringRef(WebDatabaseNameKey);
344     RetainPtr<CFStringRef> str(AdoptCF, databaseName.createCFString());
345     CFDictionarySetValue(userInfo.get(), databaseNameKey, str.get());
346
347     COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance());
348     userInfoBag->setDictionary(userInfo.get());
349
350     notifyCenter->postNotificationName(databaseDidModifyOriginName, securityOrigin.get(), userInfoBag.get());
351 }
352 \r
353 void WebKitSetWebDatabasesPathIfNecessary()\r
354 {\r
355     static bool pathSet = false;\r
356     if (pathSet)\r
357         return;\r
358 \r
359     WebCore::String databasesDirectory = WebCore::pathByAppendingComponent(WebCore::localUserSpecificStorageDirectory(), "Databases");\r
360     WebCore::DatabaseTracker::tracker().setDatabasePath(databasesDirectory);\r
361 \r
362     pathSet = true;\r
363 }\r
364 \r