diff options
Diffstat (limited to 'Source/WebKit/android/jni/WebIconDatabase.cpp')
-rw-r--r-- | Source/WebKit/android/jni/WebIconDatabase.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/Source/WebKit/android/jni/WebIconDatabase.cpp b/Source/WebKit/android/jni/WebIconDatabase.cpp new file mode 100644 index 0000000..2a660d1 --- /dev/null +++ b/Source/WebKit/android/jni/WebIconDatabase.cpp @@ -0,0 +1,237 @@ +/* + * Copyright 2006, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER OR + * 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. + */ + +#define LOG_TAG "favicons" + +#include "config.h" +#include "WebIconDatabase.h" + +#include "FileSystem.h" +#include "GraphicsJNI.h" +#include "IconDatabase.h" +#include "Image.h" +#include "IntRect.h" +#include "JavaSharedClient.h" +#include "KURL.h" +#include "WebCoreJni.h" + +#include <JNIHelp.h> +#include <JNIUtility.h> +#include <SharedBuffer.h> +#include <SkBitmap.h> +#include <SkImageDecoder.h> +#include <SkTemplates.h> +#include <pthread.h> +#include <utils/misc.h> +#include <wtf/Platform.h> +#include <wtf/text/CString.h> + +namespace android { + +jobject webcoreImageToJavaBitmap(JNIEnv* env, WebCore::Image* icon) +{ + if (!icon) + return NULL; + SkBitmap bm; + WebCore::SharedBuffer* buffer = icon->data(); + if (!buffer || !SkImageDecoder::DecodeMemory(buffer->data(), buffer->size(), + &bm, SkBitmap::kNo_Config, + SkImageDecoder::kDecodePixels_Mode)) + return NULL; + + return GraphicsJNI::createBitmap(env, new SkBitmap(bm), false, NULL); +} + +static WebIconDatabase* gIconDatabaseClient = new WebIconDatabase(); + +// XXX: Called by the IconDatabase thread +void WebIconDatabase::dispatchDidAddIconForPageURL(const WTF::String& pageURL) +{ + mNotificationsMutex.lock(); + mNotifications.append(pageURL); + if (!mDeliveryRequested) { + mDeliveryRequested = true; + JavaSharedClient::EnqueueFunctionPtr(DeliverNotifications, this); + } + mNotificationsMutex.unlock(); +} + +// Called in the WebCore thread +void WebIconDatabase::RegisterForIconNotification(WebIconDatabaseClient* client) +{ + WebIconDatabase* db = gIconDatabaseClient; + for (unsigned i = 0; i < db->mClients.size(); ++i) { + // Do not add the same client twice. + if (db->mClients[i] == client) + return; + } + gIconDatabaseClient->mClients.append(client); +} + +// Called in the WebCore thread +void WebIconDatabase::UnregisterForIconNotification(WebIconDatabaseClient* client) +{ + WebIconDatabase* db = gIconDatabaseClient; + for (unsigned i = 0; i < db->mClients.size(); ++i) { + if (db->mClients[i] == client) { + db->mClients.remove(i); + break; + } + } +} + +// Called in the WebCore thread +void WebIconDatabase::DeliverNotifications(void* v) +{ + ASSERT(v); + ((WebIconDatabase*)v)->deliverNotifications(); +} + +// Called in the WebCore thread +void WebIconDatabase::deliverNotifications() +{ + ASSERT(mDeliveryRequested); + + // Swap the notifications queue + Vector<WTF::String> queue; + mNotificationsMutex.lock(); + queue.swap(mNotifications); + mDeliveryRequested = false; + mNotificationsMutex.unlock(); + + // Swap the clients queue + Vector<WebIconDatabaseClient*> clients; + clients.swap(mClients); + + for (unsigned i = 0; i < queue.size(); ++i) { + for (unsigned j = 0; j < clients.size(); ++j) { + clients[j]->didAddIconForPageUrl(queue[i]); + } + } +} + +static void Open(JNIEnv* env, jobject obj, jstring path) +{ + WebCore::IconDatabase* iconDb = WebCore::iconDatabase(); + if (iconDb->isOpen()) + return; + iconDb->setEnabled(true); + iconDb->setClient(gIconDatabaseClient); + LOG_ASSERT(path, "No path given to nativeOpen"); + WTF::String pathStr = jstringToWtfString(env, path); + WTF::CString fullPath = WebCore::pathByAppendingComponent(pathStr, + WebCore::IconDatabase::defaultDatabaseFilename()).utf8(); + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + bool didSetPermissions = false; + if (access(fullPath.data(), F_OK) == 0) { + if (chmod(fullPath.data(), mode) == 0) + didSetPermissions = true; + } else { + int fd = open(fullPath.data(), O_CREAT, mode); + if (fd >= 0) { + close(fd); + didSetPermissions = true; + } + } + if (didSetPermissions) { + LOGV("Opening WebIconDatabase file '%s'", pathStr.latin1().data()); + bool res = iconDb->open(pathStr); + if (!res) + LOGE("Open failed!"); + } else + LOGE("Failed to set permissions on '%s'", fullPath.data()); +} + +static void Close(JNIEnv* env, jobject obj) +{ + WebCore::iconDatabase()->close(); +} + +static void RemoveAllIcons(JNIEnv* env, jobject obj) +{ + LOGV("Removing all icons"); + WebCore::iconDatabase()->removeAllIcons(); +} + +static jobject IconForPageUrl(JNIEnv* env, jobject obj, jstring url) +{ + LOG_ASSERT(url, "No url given to iconForPageUrl"); + WTF::String urlStr = jstringToWtfString(env, url); + + WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(urlStr, + WebCore::IntSize(16, 16)); + LOGV("Retrieving icon for '%s' %p", urlStr.latin1().data(), icon); + return webcoreImageToJavaBitmap(env, icon); +} + +static void RetainIconForPageUrl(JNIEnv* env, jobject obj, jstring url) +{ + LOG_ASSERT(url, "No url given to retainIconForPageUrl"); + WTF::String urlStr = jstringToWtfString(env, url); + + LOGV("Retaining icon for '%s'", urlStr.latin1().data()); + WebCore::iconDatabase()->retainIconForPageURL(urlStr); +} + +static void ReleaseIconForPageUrl(JNIEnv* env, jobject obj, jstring url) +{ + LOG_ASSERT(url, "No url given to releaseIconForPageUrl"); + WTF::String urlStr = jstringToWtfString(env, url); + + LOGV("Releasing icon for '%s'", urlStr.latin1().data()); + WebCore::iconDatabase()->releaseIconForPageURL(urlStr); +} + +/* + * JNI registration + */ +static JNINativeMethod gWebIconDatabaseMethods[] = { + { "nativeOpen", "(Ljava/lang/String;)V", + (void*) Open }, + { "nativeClose", "()V", + (void*) Close }, + { "nativeRemoveAllIcons", "()V", + (void*) RemoveAllIcons }, + { "nativeIconForPageUrl", "(Ljava/lang/String;)Landroid/graphics/Bitmap;", + (void*) IconForPageUrl }, + { "nativeRetainIconForPageUrl", "(Ljava/lang/String;)V", + (void*) RetainIconForPageUrl }, + { "nativeReleaseIconForPageUrl", "(Ljava/lang/String;)V", + (void*) ReleaseIconForPageUrl } +}; + +int registerWebIconDatabase(JNIEnv* env) +{ +#ifndef NDEBUG + jclass webIconDatabase = env->FindClass("android/webkit/WebIconDatabase"); + LOG_ASSERT(webIconDatabase, "Unable to find class android.webkit.WebIconDatabase"); + env->DeleteLocalRef(webIconDatabase); +#endif + + return jniRegisterNativeMethods(env, "android/webkit/WebIconDatabase", + gWebIconDatabaseMethods, NELEM(gWebIconDatabaseMethods)); +} + +} |