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