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 42 PassRefPtr<WebIconDatabase> WebIconDatabase::create(WebContext* context) 43 { 44 return adoptRef(new WebIconDatabase(context)); 45 } 46 47 WebIconDatabase::~WebIconDatabase() 48 { 49 } 50 51 WebIconDatabase::WebIconDatabase(WebContext* context) 52 : m_webContext(context) 53 , m_urlImportCompleted(false) 54 , m_databaseCleanupDisabled(false) 55 { 56 } 57 58 void WebIconDatabase::invalidate() 59 { 60 } 61 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 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 101 void WebIconDatabase::retainIconForPageURL(const String& pageURL) 102 { 103 if (m_iconDatabaseImpl) 104 m_iconDatabaseImpl->retainIconForPageURL(pageURL); 105 } 106 107 void WebIconDatabase::releaseIconForPageURL(const String& pageURL) 108 { 109 if (m_iconDatabaseImpl) 110 m_iconDatabaseImpl->releaseIconForPageURL(pageURL); 111 } 112 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 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 130 void WebIconDatabase::synchronousIconDataForPageURL(const String&, CoreIPC::DataReference& iconData) 131 { 132 iconData = CoreIPC::DataReference(); 133 } 134 135 void WebIconDatabase::synchronousIconURLForPageURL(const String&, String& iconURL) 136 { 137 iconURL = String(); 138 } 139 140 void WebIconDatabase::synchronousIconDataKnownForIconURL(const String&, bool& iconDataKnown) const 141 { 142 iconDataKnown = false; 143 } 144 145 void WebIconDatabase::synchronousLoadDecisionForIconURL(const String&, int& loadDecision) const 146 { 147 loadDecision = static_cast<int>(IconLoadNo); 148 } 149 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 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 187 void WebIconDatabase::removeAllIcons() 188 { 189 m_iconDatabaseImpl->removeAllIcons(); 190 } 191 192 void WebIconDatabase::checkIntegrityBeforeOpening() 193 { 194 IconDatabase::checkIntegrityBeforeOpening(); 195 } 196 197 void WebIconDatabase::close() 198 { 199 m_iconDatabaseImpl->close(); 200 } 201 202 void WebIconDatabase::initializeIconDatabaseClient(const WKIconDatabaseClient* client) 203 { 204 m_iconDatabaseClient.initialize(client); 205 } 206 207 // WebCore::IconDatabaseClient 208 bool WebIconDatabase::performImport() 209 { 210 // WebKit2 icon database doesn't currently support importing any old icon database formats. 211 return true; 212 } 213 214 void WebIconDatabase::didImportIconURLForPageURL(const String& pageURL) 215 { 216 didChangeIconForPageURL(pageURL); 217 } 218 219 void WebIconDatabase::didImportIconDataForPageURL(const String& pageURL) 220 { 221 didChangeIconForPageURL(pageURL); 222 } 223 224 void WebIconDatabase::didChangeIconForPageURL(const String& pageURL) 225 { 226 m_iconDatabaseClient.didChangeIconForPageURL(this, WebURL::create(pageURL).get()); 227 } 228 229 void WebIconDatabase::didRemoveAllIcons() 230 { 231 m_iconDatabaseClient.didRemoveAllIcons(this); 232 } 233 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 262 void WebIconDatabase::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder) 263 { 264 didReceiveWebIconDatabaseMessage(connection, messageID, decoder); 265 } 266 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