Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2006, The Android Open Source Project
      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  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 #define LOG_TAG "favicons"
     27 
     28 #include "config.h"
     29 #include "WebIconDatabase.h"
     30 
     31 #include "GraphicsJNI.h"
     32 #include "IconDatabase.h"
     33 #include "Image.h"
     34 #include "IntRect.h"
     35 #include "JavaSharedClient.h"
     36 #include "KURL.h"
     37 #include "WebCoreJni.h"
     38 
     39 #include <JNIHelp.h>
     40 #include <JNIUtility.h>
     41 #include <SkBitmap.h>
     42 #include <SkImageDecoder.h>
     43 #include <SkTemplates.h>
     44 #include <pthread.h>
     45 #include <utils/misc.h>
     46 #include <wtf/Platform.h>
     47 
     48 namespace android {
     49 
     50 jobject webcoreImageToJavaBitmap(JNIEnv* env, WebCore::Image* icon)
     51 {
     52     if (!icon)
     53         return NULL;
     54     SkBitmap bm;
     55     WebCore::SharedBuffer* buffer = icon->data();
     56     if (!buffer || !SkImageDecoder::DecodeMemory(buffer->data(), buffer->size(),
     57                                                  &bm, SkBitmap::kNo_Config,
     58                                             SkImageDecoder::kDecodePixels_Mode))
     59         return NULL;
     60 
     61     return GraphicsJNI::createBitmap(env, new SkBitmap(bm), false, NULL);
     62 }
     63 
     64 static WebIconDatabase* gIconDatabaseClient = new WebIconDatabase();
     65 
     66 // XXX: Called by the IconDatabase thread
     67 void WebIconDatabase::dispatchDidAddIconForPageURL(const WebCore::String& pageURL)
     68 {
     69     mNotificationsMutex.lock();
     70     mNotifications.append(pageURL);
     71     if (!mDeliveryRequested) {
     72         mDeliveryRequested = true;
     73         JavaSharedClient::EnqueueFunctionPtr(DeliverNotifications, this);
     74     }
     75     mNotificationsMutex.unlock();
     76 }
     77 
     78 // Called in the WebCore thread
     79 void WebIconDatabase::RegisterForIconNotification(WebIconDatabaseClient* client)
     80 {
     81     WebIconDatabase* db = gIconDatabaseClient;
     82     for (unsigned i = 0; i < db->mClients.size(); ++i) {
     83         // Do not add the same client twice.
     84         if (db->mClients[i] == client)
     85             return;
     86     }
     87     gIconDatabaseClient->mClients.append(client);
     88 }
     89 
     90 // Called in the WebCore thread
     91 void WebIconDatabase::UnregisterForIconNotification(WebIconDatabaseClient* client)
     92 {
     93     WebIconDatabase* db = gIconDatabaseClient;
     94     for (unsigned i = 0; i < db->mClients.size(); ++i) {
     95         if (db->mClients[i] == client) {
     96             db->mClients.remove(i);
     97             break;
     98         }
     99     }
    100 }
    101 
    102 // Called in the WebCore thread
    103 void WebIconDatabase::DeliverNotifications(void* v)
    104 {
    105     ASSERT(v);
    106     ((WebIconDatabase*)v)->deliverNotifications();
    107 }
    108 
    109 // Called in the WebCore thread
    110 void WebIconDatabase::deliverNotifications()
    111 {
    112     ASSERT(mDeliveryRequested);
    113 
    114     // Swap the notifications queue
    115     Vector<WebCore::String> queue;
    116     mNotificationsMutex.lock();
    117     queue.swap(mNotifications);
    118     mDeliveryRequested = false;
    119     mNotificationsMutex.unlock();
    120 
    121     // Swap the clients queue
    122     Vector<WebIconDatabaseClient*> clients;
    123     clients.swap(mClients);
    124 
    125     for (unsigned i = 0; i < queue.size(); ++i) {
    126         for (unsigned j = 0; j < clients.size(); ++j) {
    127             clients[j]->didAddIconForPageUrl(queue[i]);
    128         }
    129     }
    130 }
    131 
    132 static void Open(JNIEnv* env, jobject obj, jstring path)
    133 {
    134     WebCore::IconDatabase* iconDb = WebCore::iconDatabase();
    135     if (iconDb->isOpen())
    136         return;
    137     iconDb->setEnabled(true);
    138     iconDb->setClient(gIconDatabaseClient);
    139     LOG_ASSERT(path, "No path given to nativeOpen");
    140     WebCore::String pathStr = to_string(env, path);
    141     LOGV("Opening WebIconDatabase file '%s'", pathStr.latin1().data());
    142     bool res = iconDb->open(pathStr);
    143     if (!res)
    144         LOGE("Open failed!");
    145 }
    146 
    147 static void Close(JNIEnv* env, jobject obj)
    148 {
    149     WebCore::iconDatabase()->close();
    150 }
    151 
    152 static void RemoveAllIcons(JNIEnv* env, jobject obj)
    153 {
    154     LOGV("Removing all icons");
    155     WebCore::iconDatabase()->removeAllIcons();
    156 }
    157 
    158 static jobject IconForPageUrl(JNIEnv* env, jobject obj, jstring url)
    159 {
    160     LOG_ASSERT(url, "No url given to iconForPageUrl");
    161     WebCore::String urlStr = to_string(env, url);
    162 
    163     WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(urlStr,
    164             WebCore::IntSize(16, 16));
    165     LOGV("Retrieving icon for '%s' %p", urlStr.latin1().data(), icon);
    166     return webcoreImageToJavaBitmap(env, icon);
    167 }
    168 
    169 static void RetainIconForPageUrl(JNIEnv* env, jobject obj, jstring url)
    170 {
    171     LOG_ASSERT(url, "No url given to retainIconForPageUrl");
    172     WebCore::String urlStr = to_string(env, url);
    173 
    174     LOGV("Retaining icon for '%s'", urlStr.latin1().data());
    175     WebCore::iconDatabase()->retainIconForPageURL(urlStr);
    176 }
    177 
    178 static void ReleaseIconForPageUrl(JNIEnv* env, jobject obj, jstring url)
    179 {
    180     LOG_ASSERT(url, "No url given to releaseIconForPageUrl");
    181     WebCore::String urlStr = to_string(env, url);
    182 
    183     LOGV("Releasing icon for '%s'", urlStr.latin1().data());
    184     WebCore::iconDatabase()->releaseIconForPageURL(urlStr);
    185 }
    186 
    187 /*
    188  * JNI registration
    189  */
    190 static JNINativeMethod gWebIconDatabaseMethods[] = {
    191     { "nativeOpen", "(Ljava/lang/String;)V",
    192         (void*) Open },
    193     { "nativeClose", "()V",
    194         (void*) Close },
    195     { "nativeRemoveAllIcons", "()V",
    196         (void*) RemoveAllIcons },
    197     { "nativeIconForPageUrl", "(Ljava/lang/String;)Landroid/graphics/Bitmap;",
    198         (void*) IconForPageUrl },
    199     { "nativeRetainIconForPageUrl", "(Ljava/lang/String;)V",
    200         (void*) RetainIconForPageUrl },
    201     { "nativeReleaseIconForPageUrl", "(Ljava/lang/String;)V",
    202         (void*) ReleaseIconForPageUrl }
    203 };
    204 
    205 int register_webicondatabase(JNIEnv* env)
    206 {
    207     jclass webIconDB = env->FindClass("android/webkit/WebIconDatabase");
    208     LOG_ASSERT(webIconDB, "Unable to find class android.webkit.WebIconDatabase");
    209 
    210     return jniRegisterNativeMethods(env, "android/webkit/WebIconDatabase",
    211             gWebIconDatabaseMethods, NELEM(gWebIconDatabaseMethods));
    212 }
    213 
    214 }
    215