/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "WebIconDatabase.h"
#include "DataReference.h"
#include "Logging.h"
#include "WebContext.h"
#include "WebIconDatabaseProxyMessages.h"
#include <WebCore/FileSystem.h>
#include <WebCore/IconDatabase.h>
#include <WebCore/IconDatabaseBase.h>
#include <wtf/text/WTFString.h>
using namespace WebCore;
namespace WebKit {
PassRefPtr<WebIconDatabase> WebIconDatabase::create(WebContext* context)
{
return adoptRef(new WebIconDatabase(context));
}
WebIconDatabase::~WebIconDatabase()
{
}
WebIconDatabase::WebIconDatabase(WebContext* context)
: m_webContext(context)
, m_urlImportCompleted(false)
, m_databaseCleanupDisabled(false)
{
}
void WebIconDatabase::invalidate()
{
}
void WebIconDatabase::setDatabasePath(const String& path)
{
if (m_iconDatabaseImpl && m_iconDatabaseImpl->isOpen()) {
LOG_ERROR("Icon database already has a path and is already open. We don't currently support changing its path and reopening.");
return;
}
m_iconDatabaseImpl = IconDatabase::create();
m_iconDatabaseImpl->setClient(this);
IconDatabase::delayDatabaseCleanup();
m_databaseCleanupDisabled = true;
m_iconDatabaseImpl->setEnabled(true);
if (!m_iconDatabaseImpl->open(directoryName(path), pathGetFileName(path))) {
LOG_ERROR("Unable to open WebKit2 icon database on disk");
m_iconDatabaseImpl.clear();
setGlobalIconDatabase(0);
IconDatabase::allowDatabaseCleanup();
m_databaseCleanupDisabled = false;
}
setGlobalIconDatabase(m_iconDatabaseImpl.get());
}
void WebIconDatabase::enableDatabaseCleanup()
{
if (!m_iconDatabaseImpl) {
LOG_ERROR("Cannot enabled Icon Database cleanup - it hasn't been opened yet.");
return;
}
if (!m_databaseCleanupDisabled) {
LOG_ERROR("Attempt to enable database cleanup, but it's already enabled.");
ASSERT_NOT_REACHED();
return;
}
IconDatabase::allowDatabaseCleanup();
m_databaseCleanupDisabled = false;
}
void WebIconDatabase::retainIconForPageURL(const String& pageURL)
{
if (m_iconDatabaseImpl)
m_iconDatabaseImpl->retainIconForPageURL(pageURL);
}
void WebIconDatabase::releaseIconForPageURL(const String& pageURL)
{
if (m_iconDatabaseImpl)
m_iconDatabaseImpl->releaseIconForPageURL(pageURL);
}
void WebIconDatabase::setIconURLForPageURL(const String& iconURL, const String& pageURL)
{
LOG(IconDatabase, "WK2 UIProcess setting icon URL %s for page URL %s", iconURL.ascii().data(), pageURL.ascii().data());
if (m_iconDatabaseImpl)
m_iconDatabaseImpl->setIconURLForPageURL(iconURL, pageURL);
}
void WebIconDatabase::setIconDataForIconURL(const CoreIPC::DataReference& iconData, const String& iconURL)
{
LOG(IconDatabase, "WK2 UIProcess setting icon data (%i bytes) for page URL %s", (int)iconData.size(), iconURL.ascii().data());
if (!m_iconDatabaseImpl)
return;
RefPtr<SharedBuffer> buffer = SharedBuffer::create(iconData.data(), iconData.size());
m_iconDatabaseImpl->setIconDataForIconURL(buffer.release(), iconURL);
}
void WebIconDatabase::synchronousIconDataForPageURL(const String&, CoreIPC::DataReference& iconData)
{
iconData = CoreIPC::DataReference();
}
void WebIconDatabase::synchronousIconURLForPageURL(const String&, String& iconURL)
{
iconURL = String();
}
void WebIconDatabase::synchronousIconDataKnownForIconURL(const String&, bool& iconDataKnown) const
{
iconDataKnown = false;
}
void WebIconDatabase::synchronousLoadDecisionForIconURL(const String&, int& loadDecision) const
{
loadDecision = static_cast<int>(IconLoadNo);
}
void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t callbackID)
{
LOG(IconDatabase, "WK2 UIProcess getting load decision for icon URL %s with callback ID %lli", iconURL.ascii().data(), static_cast<long long>(callbackID));
if (!m_webContext)
return;
if (!m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || iconURL.isEmpty()) {
// FIXME (Multi-WebProcess): We need to know which connection to send this message to.
m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(IconLoadNo), callbackID));
return;
}
// If the decision hasn't been read from disk yet, set this url and callback ID aside to be notifed later
IconLoadDecision decision = m_iconDatabaseImpl->synchronousLoadDecisionForIconURL(iconURL, 0);
if (decision == IconLoadUnknown) {
// We should never get an unknown load decision after the URL import has completed.
ASSERT(!m_urlImportCompleted);
m_pendingLoadDecisionURLMap.set(callbackID, iconURL);
return;
}
// FIXME (Multi-WebProcess): We need to know which connection to send this message to.
m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision((int)decision, callbackID));
}
Image* WebIconDatabase::imageForPageURL(const String& pageURL)
{
if (!m_webContext || !m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || pageURL.isEmpty())
return 0;
// The WebCore IconDatabase ignores the passed in size parameter.
// If that changes we'll need to rethink how this API is exposed.
return m_iconDatabaseImpl->synchronousIconForPageURL(pageURL, WebCore::IntSize(32, 32));
}
void WebIconDatabase::removeAllIcons()
{
m_iconDatabaseImpl->removeAllIcons();
}
void WebIconDatabase::checkIntegrityBeforeOpening()
{
IconDatabase::checkIntegrityBeforeOpening();
}
void WebIconDatabase::close()
{
m_iconDatabaseImpl->close();
}
void WebIconDatabase::initializeIconDatabaseClient(const WKIconDatabaseClient* client)
{
m_iconDatabaseClient.initialize(client);
}
// WebCore::IconDatabaseClient
bool WebIconDatabase::performImport()
{
// WebKit2 icon database doesn't currently support importing any old icon database formats.
return true;
}
void WebIconDatabase::didImportIconURLForPageURL(const String& pageURL)
{
didChangeIconForPageURL(pageURL);
}
void WebIconDatabase::didImportIconDataForPageURL(const String& pageURL)
{
didChangeIconForPageURL(pageURL);
}
void WebIconDatabase::didChangeIconForPageURL(const String& pageURL)
{
m_iconDatabaseClient.didChangeIconForPageURL(this, WebURL::create(pageURL).get());
}
void WebIconDatabase::didRemoveAllIcons()
{
m_iconDatabaseClient.didRemoveAllIcons(this);
}
void WebIconDatabase::didFinishURLImport()
{
if (!m_webContext)
return;
ASSERT(!m_urlImportCompleted);
LOG(IconDatabase, "WK2 UIProcess URL import complete, notifying all %i pending page URL load decisions", m_pendingLoadDecisionURLMap.size());
HashMap<uint64_t, String>::iterator i = m_pendingLoadDecisionURLMap.begin();
HashMap<uint64_t, String>::iterator end = m_pendingLoadDecisionURLMap.end();
for (; i != end; ++i) {
LOG(IconDatabase, "WK2 UIProcess performing delayed callback on callback ID %i for page url %s", (int)i->first, i->second.ascii().data());
IconLoadDecision decision = m_iconDatabaseImpl->synchronousLoadDecisionForIconURL(i->second, 0);
// Decisions should never be unknown after the inital import is complete
ASSERT(decision != IconLoadUnknown);
// FIXME (Multi-WebProcess): We need to know which connection to send this message to.
m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(decision), i->first));
}
m_pendingLoadDecisionURLMap.clear();
m_urlImportCompleted = true;
}
void WebIconDatabase::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder)
{
didReceiveWebIconDatabaseMessage(connection, messageID, decoder);
}
CoreIPC::SyncReplyMode WebIconDatabase::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder, CoreIPC::ArgumentEncoder* reply)
{
return didReceiveSyncWebIconDatabaseMessage(connection, messageID, decoder, reply);
}
} // namespace WebKit