1 /*
2 * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "WebIconDatabase.h"
28
29 #include "DataReference.h"
30 #include "Logging.h"
31 #include "WebContext.h"
32 #include "WebIconDatabaseProxyMessages.h"
33 #include <WebCore/FileSystem.h>
34 #include <WebCore/IconDatabase.h>
35 #include <WebCore/IconDatabaseBase.h>
36 #include <wtf/text/WTFString.h>
37
38 using namespace WebCore;
39
40 namespace WebKit {
41
create(WebContext * context)42 PassRefPtr<WebIconDatabase> WebIconDatabase::create(WebContext* context)
43 {
44 return adoptRef(new WebIconDatabase(context));
45 }
46
~WebIconDatabase()47 WebIconDatabase::~WebIconDatabase()
48 {
49 }
50
WebIconDatabase(WebContext * context)51 WebIconDatabase::WebIconDatabase(WebContext* context)
52 : m_webContext(context)
53 , m_urlImportCompleted(false)
54 , m_databaseCleanupDisabled(false)
55 {
56 }
57
invalidate()58 void WebIconDatabase::invalidate()
59 {
60 }
61
setDatabasePath(const String & path)62 void WebIconDatabase::setDatabasePath(const String& path)
63 {
64 if (m_iconDatabaseImpl && m_iconDatabaseImpl->isOpen()) {
65 LOG_ERROR("Icon database already has a path and is already open. We don't currently support changing its path and reopening.");
66 return;
67 }
68
69 m_iconDatabaseImpl = IconDatabase::create();
70 m_iconDatabaseImpl->setClient(this);
71 IconDatabase::delayDatabaseCleanup();
72 m_databaseCleanupDisabled = true;
73 m_iconDatabaseImpl->setEnabled(true);
74 if (!m_iconDatabaseImpl->open(directoryName(path), pathGetFileName(path))) {
75 LOG_ERROR("Unable to open WebKit2 icon database on disk");
76 m_iconDatabaseImpl.clear();
77 setGlobalIconDatabase(0);
78 IconDatabase::allowDatabaseCleanup();
79 m_databaseCleanupDisabled = false;
80 }
81 setGlobalIconDatabase(m_iconDatabaseImpl.get());
82 }
83
enableDatabaseCleanup()84 void WebIconDatabase::enableDatabaseCleanup()
85 {
86 if (!m_iconDatabaseImpl) {
87 LOG_ERROR("Cannot enabled Icon Database cleanup - it hasn't been opened yet.");
88 return;
89 }
90
91 if (!m_databaseCleanupDisabled) {
92 LOG_ERROR("Attempt to enable database cleanup, but it's already enabled.");
93 ASSERT_NOT_REACHED();
94 return;
95 }
96
97 IconDatabase::allowDatabaseCleanup();
98 m_databaseCleanupDisabled = false;
99 }
100
retainIconForPageURL(const String & pageURL)101 void WebIconDatabase::retainIconForPageURL(const String& pageURL)
102 {
103 if (m_iconDatabaseImpl)
104 m_iconDatabaseImpl->retainIconForPageURL(pageURL);
105 }
106
releaseIconForPageURL(const String & pageURL)107 void WebIconDatabase::releaseIconForPageURL(const String& pageURL)
108 {
109 if (m_iconDatabaseImpl)
110 m_iconDatabaseImpl->releaseIconForPageURL(pageURL);
111 }
112
setIconURLForPageURL(const String & iconURL,const String & pageURL)113 void WebIconDatabase::setIconURLForPageURL(const String& iconURL, const String& pageURL)
114 {
115 LOG(IconDatabase, "WK2 UIProcess setting icon URL %s for page URL %s", iconURL.ascii().data(), pageURL.ascii().data());
116 if (m_iconDatabaseImpl)
117 m_iconDatabaseImpl->setIconURLForPageURL(iconURL, pageURL);
118 }
119
setIconDataForIconURL(const CoreIPC::DataReference & iconData,const String & iconURL)120 void WebIconDatabase::setIconDataForIconURL(const CoreIPC::DataReference& iconData, const String& iconURL)
121 {
122 LOG(IconDatabase, "WK2 UIProcess setting icon data (%i bytes) for page URL %s", (int)iconData.size(), iconURL.ascii().data());
123 if (!m_iconDatabaseImpl)
124 return;
125
126 RefPtr<SharedBuffer> buffer = SharedBuffer::create(iconData.data(), iconData.size());
127 m_iconDatabaseImpl->setIconDataForIconURL(buffer.release(), iconURL);
128 }
129
synchronousIconDataForPageURL(const String &,CoreIPC::DataReference & iconData)130 void WebIconDatabase::synchronousIconDataForPageURL(const String&, CoreIPC::DataReference& iconData)
131 {
132 iconData = CoreIPC::DataReference();
133 }
134
synchronousIconURLForPageURL(const String &,String & iconURL)135 void WebIconDatabase::synchronousIconURLForPageURL(const String&, String& iconURL)
136 {
137 iconURL = String();
138 }
139
synchronousIconDataKnownForIconURL(const String &,bool & iconDataKnown) const140 void WebIconDatabase::synchronousIconDataKnownForIconURL(const String&, bool& iconDataKnown) const
141 {
142 iconDataKnown = false;
143 }
144
synchronousLoadDecisionForIconURL(const String &,int & loadDecision) const145 void WebIconDatabase::synchronousLoadDecisionForIconURL(const String&, int& loadDecision) const
146 {
147 loadDecision = static_cast<int>(IconLoadNo);
148 }
149
getLoadDecisionForIconURL(const String & iconURL,uint64_t callbackID)150 void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t callbackID)
151 {
152 LOG(IconDatabase, "WK2 UIProcess getting load decision for icon URL %s with callback ID %lli", iconURL.ascii().data(), static_cast<long long>(callbackID));
153
154 if (!m_webContext)
155 return;
156
157 if (!m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || iconURL.isEmpty()) {
158 // FIXME (Multi-WebProcess): We need to know which connection to send this message to.
159 m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(IconLoadNo), callbackID));
160 return;
161 }
162
163 // If the decision hasn't been read from disk yet, set this url and callback ID aside to be notifed later
164 IconLoadDecision decision = m_iconDatabaseImpl->synchronousLoadDecisionForIconURL(iconURL, 0);
165 if (decision == IconLoadUnknown) {
166 // We should never get an unknown load decision after the URL import has completed.
167 ASSERT(!m_urlImportCompleted);
168
169 m_pendingLoadDecisionURLMap.set(callbackID, iconURL);
170 return;
171 }
172
173 // FIXME (Multi-WebProcess): We need to know which connection to send this message to.
174 m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision((int)decision, callbackID));
175 }
176
imageForPageURL(const String & pageURL)177 Image* WebIconDatabase::imageForPageURL(const String& pageURL)
178 {
179 if (!m_webContext || !m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || pageURL.isEmpty())
180 return 0;
181
182 // The WebCore IconDatabase ignores the passed in size parameter.
183 // If that changes we'll need to rethink how this API is exposed.
184 return m_iconDatabaseImpl->synchronousIconForPageURL(pageURL, WebCore::IntSize(32, 32));
185 }
186
removeAllIcons()187 void WebIconDatabase::removeAllIcons()
188 {
189 m_iconDatabaseImpl->removeAllIcons();
190 }
191
checkIntegrityBeforeOpening()192 void WebIconDatabase::checkIntegrityBeforeOpening()
193 {
194 IconDatabase::checkIntegrityBeforeOpening();
195 }
196
close()197 void WebIconDatabase::close()
198 {
199 m_iconDatabaseImpl->close();
200 }
201
initializeIconDatabaseClient(const WKIconDatabaseClient * client)202 void WebIconDatabase::initializeIconDatabaseClient(const WKIconDatabaseClient* client)
203 {
204 m_iconDatabaseClient.initialize(client);
205 }
206
207 // WebCore::IconDatabaseClient
performImport()208 bool WebIconDatabase::performImport()
209 {
210 // WebKit2 icon database doesn't currently support importing any old icon database formats.
211 return true;
212 }
213
didImportIconURLForPageURL(const String & pageURL)214 void WebIconDatabase::didImportIconURLForPageURL(const String& pageURL)
215 {
216 didChangeIconForPageURL(pageURL);
217 }
218
didImportIconDataForPageURL(const String & pageURL)219 void WebIconDatabase::didImportIconDataForPageURL(const String& pageURL)
220 {
221 didChangeIconForPageURL(pageURL);
222 }
223
didChangeIconForPageURL(const String & pageURL)224 void WebIconDatabase::didChangeIconForPageURL(const String& pageURL)
225 {
226 m_iconDatabaseClient.didChangeIconForPageURL(this, WebURL::create(pageURL).get());
227 }
228
didRemoveAllIcons()229 void WebIconDatabase::didRemoveAllIcons()
230 {
231 m_iconDatabaseClient.didRemoveAllIcons(this);
232 }
233
didFinishURLImport()234 void WebIconDatabase::didFinishURLImport()
235 {
236 if (!m_webContext)
237 return;
238
239 ASSERT(!m_urlImportCompleted);
240
241 LOG(IconDatabase, "WK2 UIProcess URL import complete, notifying all %i pending page URL load decisions", m_pendingLoadDecisionURLMap.size());
242
243 HashMap<uint64_t, String>::iterator i = m_pendingLoadDecisionURLMap.begin();
244 HashMap<uint64_t, String>::iterator end = m_pendingLoadDecisionURLMap.end();
245
246 for (; i != end; ++i) {
247 LOG(IconDatabase, "WK2 UIProcess performing delayed callback on callback ID %i for page url %s", (int)i->first, i->second.ascii().data());
248 IconLoadDecision decision = m_iconDatabaseImpl->synchronousLoadDecisionForIconURL(i->second, 0);
249
250 // Decisions should never be unknown after the inital import is complete
251 ASSERT(decision != IconLoadUnknown);
252
253 // FIXME (Multi-WebProcess): We need to know which connection to send this message to.
254 m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(decision), i->first));
255 }
256
257 m_pendingLoadDecisionURLMap.clear();
258
259 m_urlImportCompleted = true;
260 }
261
didReceiveMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * decoder)262 void WebIconDatabase::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder)
263 {
264 didReceiveWebIconDatabaseMessage(connection, messageID, decoder);
265 }
266
didReceiveSyncMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * decoder,CoreIPC::ArgumentEncoder * reply)267 CoreIPC::SyncReplyMode WebIconDatabase::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder, CoreIPC::ArgumentEncoder* reply)
268 {
269 return didReceiveSyncWebIconDatabaseMessage(connection, messageID, decoder, reply);
270 }
271
272 } // namespace WebKit
273