• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "FileSystem.h"
32 #include "GraphicsJNI.h"
33 #include "IconDatabase.h"
34 #include "Image.h"
35 #include "IntRect.h"
36 #include "JavaSharedClient.h"
37 #include "KURL.h"
38 #include "WebCoreJni.h"
39 
40 #include <JNIHelp.h>
41 #include <JNIUtility.h>
42 #include <SharedBuffer.h>
43 #include <SkBitmap.h>
44 #include <SkImageDecoder.h>
45 #include <SkTemplates.h>
46 #include <pthread.h>
47 #include <utils/misc.h>
48 #include <wtf/Platform.h>
49 #include <wtf/text/CString.h>
50 
51 namespace android {
52 
webcoreImageToJavaBitmap(JNIEnv * env,WebCore::Image * icon)53 jobject webcoreImageToJavaBitmap(JNIEnv* env, WebCore::Image* icon)
54 {
55     if (!icon)
56         return NULL;
57     SkBitmap bm;
58     WebCore::SharedBuffer* buffer = icon->data();
59     if (!buffer || !SkImageDecoder::DecodeMemory(buffer->data(), buffer->size(),
60                                                  &bm, SkBitmap::kNo_Config,
61                                             SkImageDecoder::kDecodePixels_Mode))
62         return NULL;
63 
64     return GraphicsJNI::createBitmap(env, new SkBitmap(bm), false, NULL);
65 }
66 
67 static WebIconDatabase* gIconDatabaseClient = new WebIconDatabase();
68 
performImport()69 bool WebIconDatabase::performImport()
70 {
71     // We don't do do any old-style database importing.
72     return true;
73 }
74 
75 // Called on the WebCore thread
didImportIconURLForPageURL(const WTF::String & pageURL)76 void WebIconDatabase::didImportIconURLForPageURL(const WTF::String& pageURL)
77 {
78     // FIXME: After http://trac.webkit.org/changeset/81719 this method is called
79     // on the WebCore thread, so switching threads via this queue is superfluous
80     // and should be removed. http://b/4565022
81     mNotificationsMutex.lock();
82     mNotifications.append(pageURL);
83     if (!mDeliveryRequested) {
84         mDeliveryRequested = true;
85         JavaSharedClient::EnqueueFunctionPtr(DeliverNotifications, this);
86     }
87     mNotificationsMutex.unlock();
88 }
89 
didImportIconDataForPageURL(const WTF::String & pageURL)90 void WebIconDatabase::didImportIconDataForPageURL(const WTF::String& pageURL)
91 {
92     // WebKit1 only has a single "icon did change" notification.
93     didImportIconURLForPageURL(pageURL);
94 }
95 
didChangeIconForPageURL(const WTF::String & pageURL)96 void WebIconDatabase::didChangeIconForPageURL(const WTF::String& pageURL)
97 {
98     // WebKit1 only has a single "icon did change" notification.
99     didImportIconURLForPageURL(pageURL);
100 }
101 
didRemoveAllIcons()102 void WebIconDatabase::didRemoveAllIcons()
103 {
104 }
105 
didFinishURLImport()106 void WebIconDatabase::didFinishURLImport()
107 {
108 }
109 
110 // Called in the WebCore thread
RegisterForIconNotification(WebIconDatabaseClient * client)111 void WebIconDatabase::RegisterForIconNotification(WebIconDatabaseClient* client)
112 {
113     WebIconDatabase* db = gIconDatabaseClient;
114     for (unsigned i = 0; i < db->mClients.size(); ++i) {
115         // Do not add the same client twice.
116         if (db->mClients[i] == client)
117             return;
118     }
119     gIconDatabaseClient->mClients.append(client);
120 }
121 
122 // Called in the WebCore thread
UnregisterForIconNotification(WebIconDatabaseClient * client)123 void WebIconDatabase::UnregisterForIconNotification(WebIconDatabaseClient* client)
124 {
125     WebIconDatabase* db = gIconDatabaseClient;
126     for (unsigned i = 0; i < db->mClients.size(); ++i) {
127         if (db->mClients[i] == client) {
128             db->mClients.remove(i);
129             break;
130         }
131     }
132 }
133 
134 // Called in the WebCore thread
DeliverNotifications(void * v)135 void WebIconDatabase::DeliverNotifications(void* v)
136 {
137     ASSERT(v);
138     ((WebIconDatabase*)v)->deliverNotifications();
139 }
140 
141 // Called in the WebCore thread
deliverNotifications()142 void WebIconDatabase::deliverNotifications()
143 {
144     ASSERT(mDeliveryRequested);
145 
146     // Swap the notifications queue
147     Vector<WTF::String> queue;
148     mNotificationsMutex.lock();
149     queue.swap(mNotifications);
150     mDeliveryRequested = false;
151     mNotificationsMutex.unlock();
152 
153     // Swap the clients queue
154     Vector<WebIconDatabaseClient*> clients;
155     clients.swap(mClients);
156 
157     for (unsigned i = 0; i < queue.size(); ++i) {
158         for (unsigned j = 0; j < clients.size(); ++j) {
159             clients[j]->didAddIconForPageUrl(queue[i]);
160         }
161     }
162 }
163 
Open(JNIEnv * env,jobject obj,jstring path)164 static void Open(JNIEnv* env, jobject obj, jstring path)
165 {
166     WebCore::IconDatabaseBase& iconDb = WebCore::iconDatabase();
167     if (iconDb.isOpen())
168         return;
169     iconDb.setEnabled(true);
170     iconDb.setClient(gIconDatabaseClient);
171     LOG_ASSERT(path, "No path given to nativeOpen");
172     WTF::String pathStr = jstringToWtfString(env, path);
173     WTF::CString fullPath = WebCore::pathByAppendingComponent(pathStr,
174             WebCore::IconDatabase::defaultDatabaseFilename()).utf8();
175     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
176     bool didSetPermissions = false;
177     if (access(fullPath.data(), F_OK) == 0) {
178         if (chmod(fullPath.data(), mode) == 0)
179             didSetPermissions = true;
180     } else {
181         int fd = open(fullPath.data(), O_CREAT, mode);
182         if (fd >= 0) {
183             close(fd);
184             didSetPermissions = true;
185         }
186     }
187     if (didSetPermissions) {
188         LOGV("Opening WebIconDatabase file '%s'", pathStr.latin1().data());
189         bool res = iconDb.open(pathStr, WebCore::IconDatabase::defaultDatabaseFilename());
190         if (!res)
191             LOGE("Open failed!");
192     } else
193         LOGE("Failed to set permissions on '%s'", fullPath.data());
194 }
195 
Close(JNIEnv * env,jobject obj)196 static void Close(JNIEnv* env, jobject obj)
197 {
198     WebCore::iconDatabase().close();
199 }
200 
RemoveAllIcons(JNIEnv * env,jobject obj)201 static void RemoveAllIcons(JNIEnv* env, jobject obj)
202 {
203     LOGV("Removing all icons");
204     WebCore::iconDatabase().removeAllIcons();
205 }
206 
IconForPageUrl(JNIEnv * env,jobject obj,jstring url)207 static jobject IconForPageUrl(JNIEnv* env, jobject obj, jstring url)
208 {
209     LOG_ASSERT(url, "No url given to iconForPageUrl");
210     WTF::String urlStr = jstringToWtfString(env, url);
211 
212     // FIXME: This method should not be used from outside WebCore and will be removed.
213     // http://trac.webkit.org/changeset/81484
214     WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(urlStr, WebCore::IntSize(16, 16));
215     LOGV("Retrieving icon for '%s' %p", urlStr.latin1().data(), icon);
216     return webcoreImageToJavaBitmap(env, icon);
217 }
218 
RetainIconForPageUrl(JNIEnv * env,jobject obj,jstring url)219 static void RetainIconForPageUrl(JNIEnv* env, jobject obj, jstring url)
220 {
221     LOG_ASSERT(url, "No url given to retainIconForPageUrl");
222     WTF::String urlStr = jstringToWtfString(env, url);
223 
224     LOGV("Retaining icon for '%s'", urlStr.latin1().data());
225     WebCore::iconDatabase().retainIconForPageURL(urlStr);
226 }
227 
ReleaseIconForPageUrl(JNIEnv * env,jobject obj,jstring url)228 static void ReleaseIconForPageUrl(JNIEnv* env, jobject obj, jstring url)
229 {
230     LOG_ASSERT(url, "No url given to releaseIconForPageUrl");
231     WTF::String urlStr = jstringToWtfString(env, url);
232 
233     LOGV("Releasing icon for '%s'", urlStr.latin1().data());
234     WebCore::iconDatabase().releaseIconForPageURL(urlStr);
235 }
236 
237 /*
238  * JNI registration
239  */
240 static JNINativeMethod gWebIconDatabaseMethods[] = {
241     { "nativeOpen", "(Ljava/lang/String;)V",
242         (void*) Open },
243     { "nativeClose", "()V",
244         (void*) Close },
245     { "nativeRemoveAllIcons", "()V",
246         (void*) RemoveAllIcons },
247     { "nativeIconForPageUrl", "(Ljava/lang/String;)Landroid/graphics/Bitmap;",
248         (void*) IconForPageUrl },
249     { "nativeRetainIconForPageUrl", "(Ljava/lang/String;)V",
250         (void*) RetainIconForPageUrl },
251     { "nativeReleaseIconForPageUrl", "(Ljava/lang/String;)V",
252         (void*) ReleaseIconForPageUrl }
253 };
254 
registerWebIconDatabase(JNIEnv * env)255 int registerWebIconDatabase(JNIEnv* env)
256 {
257 #ifndef NDEBUG
258     jclass webIconDatabase = env->FindClass("android/webkit/WebIconDatabase");
259     LOG_ASSERT(webIconDatabase, "Unable to find class android.webkit.WebIconDatabase");
260     env->DeleteLocalRef(webIconDatabase);
261 #endif
262 
263     return jniRegisterNativeMethods(env, "android/webkit/WebIconDatabase",
264             gWebIconDatabaseMethods, NELEM(gWebIconDatabaseMethods));
265 }
266 
267 }
268