[iOS] Upstream PLATFORM(IOS) changes to Source/WebKit/
[WebKit-https.git] / Source / WebKit / mac / Storage / WebDatabaseManagerClient.mm
1 /*
2  * Copyright (C) 2007,2012 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25  
26 #import "WebDatabaseManagerClient.h"
27
28 #if ENABLE(SQL_DATABASE)
29
30 #import "WebDatabaseManagerPrivate.h"
31 #import "WebSecurityOriginInternal.h"
32 #import <wtf/MainThread.h>
33 #import <wtf/RetainPtr.h>
34 #import <WebCore/SecurityOrigin.h>
35
36 #if PLATFORM(IOS)
37 #import <WebCore/WebCoreThread.h>
38 #endif
39
40 using namespace WebCore;
41
42 #if PLATFORM(IOS)
43 static CFStringRef WebDatabaseOriginWasAddedNotification = CFSTR("com.apple.MobileSafariSettings.WebDatabaseOriginWasAddedNotification");
44 static CFStringRef WebDatabaseWasDeletedNotification = CFSTR("com.apple.MobileSafariSettings.WebDatabaseWasDeletedNotification");
45 static CFStringRef WebDatabaseOriginWasDeletedNotification = CFSTR("com.apple.MobileSafariSettings.WebDatabaseOriginWasDeletedNotification");
46 #endif
47
48 WebDatabaseManagerClient* WebDatabaseManagerClient::sharedWebDatabaseManagerClient()
49 {
50     static WebDatabaseManagerClient* sharedClient = new WebDatabaseManagerClient();
51     return sharedClient;
52 }
53
54 #if PLATFORM(IOS)
55 static void onNewDatabaseOriginAdded(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
56 {
57     ASSERT(observer);
58     
59     WebDatabaseManagerClient* client = reinterpret_cast<WebDatabaseManagerClient*>(observer);
60     client->newDatabaseOriginWasAdded();
61 }
62
63 static void onDatabaseDeleted(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
64 {
65     ASSERT(observer);
66     
67     WebDatabaseManagerClient* client = reinterpret_cast<WebDatabaseManagerClient*>(observer);
68     client->databaseWasDeleted();
69 }
70
71 static void onDatabaseOriginDeleted(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
72 {
73     ASSERT(observer);
74     
75     WebDatabaseManagerClient* client = reinterpret_cast<WebDatabaseManagerClient*>(observer);
76     client->databaseOriginWasDeleted();
77 }
78 #endif
79
80 WebDatabaseManagerClient::WebDatabaseManagerClient()
81 #if PLATFORM(IOS)
82     : m_isHandlingNewDatabaseOriginNotification(false)
83     , m_isHandlingDeleteDatabaseNotification(false)
84     , m_isHandlingDeleteDatabaseOriginNotification(false)
85 #endif
86 {
87 #if PLATFORM(IOS)
88     CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter(); 
89     CFNotificationCenterAddObserver(center, this, onNewDatabaseOriginAdded, WebDatabaseOriginWasAddedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
90     CFNotificationCenterAddObserver(center, this, onDatabaseDeleted, WebDatabaseWasDeletedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
91     CFNotificationCenterAddObserver(center, this, onDatabaseOriginDeleted, WebDatabaseOriginWasDeletedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);    
92 #endif
93 }
94
95 WebDatabaseManagerClient::~WebDatabaseManagerClient()
96 {
97 #if PLATFORM(IOS)
98     CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, 0, 0);
99 #endif
100 }
101
102 class DidModifyOriginData {
103     WTF_MAKE_NONCOPYABLE(DidModifyOriginData);
104 public:
105     static void dispatchToMainThread(WebDatabaseManagerClient* client, SecurityOrigin* origin)
106     {
107         DidModifyOriginData* context = new DidModifyOriginData(client, origin->isolatedCopy());
108         callOnMainThread(&DidModifyOriginData::dispatchDidModifyOriginOnMainThread, context);
109     }
110
111 private:
112     DidModifyOriginData(WebDatabaseManagerClient* client, PassRefPtr<SecurityOrigin> origin)
113         : client(client)
114         , origin(origin)
115     {
116     }
117
118     static void dispatchDidModifyOriginOnMainThread(void* context)
119     {
120         ASSERT(isMainThread());
121         DidModifyOriginData* info = static_cast<DidModifyOriginData*>(context);
122         info->client->dispatchDidModifyOrigin(info->origin.get());
123         delete info;
124     }
125
126     WebDatabaseManagerClient* client;
127     RefPtr<SecurityOrigin> origin;
128 };
129
130 void WebDatabaseManagerClient::dispatchDidModifyOrigin(SecurityOrigin* origin)
131 {
132     if (!isMainThread()) {
133         DidModifyOriginData::dispatchToMainThread(this, origin);
134         return;
135     }
136
137     RetainPtr<WebSecurityOrigin> webSecurityOrigin = adoptNS([[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin]);
138
139     [[NSNotificationCenter defaultCenter] postNotificationName:WebDatabaseDidModifyOriginNotification 
140                                                         object:webSecurityOrigin.get()];
141 }
142
143 void WebDatabaseManagerClient::dispatchDidModifyDatabase(SecurityOrigin* origin, const String& databaseIdentifier)
144 {
145     if (!isMainThread()) {
146         DidModifyOriginData::dispatchToMainThread(this, origin);
147         return;
148     }
149
150     RetainPtr<WebSecurityOrigin> webSecurityOrigin = adoptNS([[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin]);
151     RetainPtr<NSDictionary> userInfo = adoptNS([[NSDictionary alloc] 
152                                                initWithObjectsAndKeys:(NSString *)databaseIdentifier, WebDatabaseIdentifierKey, nil]);
153     
154     [[NSNotificationCenter defaultCenter] postNotificationName:WebDatabaseDidModifyDatabaseNotification
155                                                         object:webSecurityOrigin.get()
156                                                       userInfo:userInfo.get()];
157 }
158
159 #if PLATFORM(IOS)
160 void WebDatabaseManagerClient::dispatchDidAddNewOrigin(SecurityOrigin*)
161 {    
162     m_isHandlingNewDatabaseOriginNotification = true;
163     // Send a notification to all apps that a new origin has been added, so other apps with opened database can refresh their origin maps.
164     CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), WebDatabaseOriginWasAddedNotification, 0, 0, true);
165 }
166
167 void WebDatabaseManagerClient::dispatchDidDeleteDatabase()
168 {
169     m_isHandlingDeleteDatabaseNotification = true;
170     // Send a notification to all apps that a database has been deleted, so other apps with the deleted database open will close it properly.
171     CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), WebDatabaseWasDeletedNotification, 0, 0, true);
172 }
173
174 void WebDatabaseManagerClient::dispatchDidDeleteDatabaseOrigin()
175 {
176     m_isHandlingDeleteDatabaseOriginNotification = true;
177     // Send a notification to all apps that an origin has been deleted, so other apps can update their origin maps.
178     CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), WebDatabaseOriginWasDeletedNotification, 0, 0, true);
179 }
180
181 void WebDatabaseManagerClient::newDatabaseOriginWasAdded()
182 {
183     // Locks the WebThread for the rest of the run loop.
184     WebThreadLock();
185
186     // If this is the process that added the new origin, its quota map should have been updated
187     // and does not need to be invalidated.
188     if (m_isHandlingNewDatabaseOriginNotification) {
189         m_isHandlingNewDatabaseOriginNotification = false;
190         return;
191     }
192     
193     databaseOriginsDidChange();
194 }
195
196 void WebDatabaseManagerClient::databaseWasDeleted()
197 {
198     // Locks the WebThread for the rest of the run loop.
199     WebThreadLock();
200     
201     // If this is the process that added the new origin, its quota map should have been updated
202     // and does not need to be invalidated.
203     if (m_isHandlingDeleteDatabaseNotification) {
204         m_isHandlingDeleteDatabaseNotification = false;
205         return;
206     }
207     
208     DatabaseTracker::tracker().removeDeletedOpenedDatabases();
209 }
210
211 void WebDatabaseManagerClient::databaseOriginWasDeleted()
212 {
213     // Locks the WebThread for the rest of the run loop.
214     WebThreadLock();
215     
216     // If this is the process that added the new origin, its quota map should have been updated
217     // and does not need to be invalidated.
218     if (m_isHandlingDeleteDatabaseOriginNotification) {
219         m_isHandlingDeleteDatabaseOriginNotification = false;
220         return;
221     }
222
223     databaseOriginsDidChange();
224 }
225
226 void WebDatabaseManagerClient::databaseOriginsDidChange()
227 {
228     // Send a notification (within the app) about the origins change.  If an app needs to update its UI when the origins change
229     // (such as Safari Settings), it can listen for that notification.
230     CFNotificationCenterPostNotification(CFNotificationCenterGetLocalCenter(), WebDatabaseOriginsDidChangeNotification, 0, 0, true);
231 }
232
233 #endif // PLATFORM(IOS)
234
235 #endif