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