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