WebIconDatabase.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.webkit; 18 19import android.os.Handler; 20import android.os.Message; 21import android.graphics.Bitmap; 22 23import java.util.Vector; 24 25/** 26 * Functions for manipulating the icon database used by WebView. 27 * These functions require that a WebView be constructed before being invoked 28 * and WebView.getIconDatabase() will return a WebIconDatabase object. This 29 * WebIconDatabase object is a single instance and all methods operate on that 30 * single object. 31 */ 32public final class WebIconDatabase { 33 // Global instance of a WebIconDatabase 34 private static WebIconDatabase sIconDatabase; 35 // EventHandler for handling messages before and after the WebCore thread is 36 // ready. 37 private final EventHandler mEventHandler = new EventHandler(); 38 39 // Class to handle messages before WebCore is ready 40 private class EventHandler extends Handler { 41 // Message ids 42 static final int OPEN = 0; 43 static final int CLOSE = 1; 44 static final int REMOVE_ALL = 2; 45 static final int REQUEST_ICON = 3; 46 static final int RETAIN_ICON = 4; 47 static final int RELEASE_ICON = 5; 48 // Message for dispatching icon request results 49 private static final int ICON_RESULT = 10; 50 // Actual handler that runs in WebCore thread 51 private Handler mHandler; 52 // Vector of messages before the WebCore thread is ready 53 private Vector<Message> mMessages = new Vector<Message>(); 54 // Class to handle a result dispatch 55 private class IconResult { 56 private final String mUrl; 57 private final Bitmap mIcon; 58 private final IconListener mListener; 59 IconResult(String url, Bitmap icon, IconListener l) { 60 mUrl = url; 61 mIcon = icon; 62 mListener = l; 63 } 64 void dispatch() { 65 mListener.onReceivedIcon(mUrl, mIcon); 66 } 67 } 68 69 @Override 70 public void handleMessage(Message msg) { 71 // Note: This is the message handler for the UI thread. 72 switch (msg.what) { 73 case ICON_RESULT: 74 ((IconResult) msg.obj).dispatch(); 75 break; 76 } 77 } 78 79 // Called by WebCore thread to create the actual handler 80 private synchronized void createHandler() { 81 if (mHandler == null) { 82 mHandler = new Handler() { 83 @Override 84 public void handleMessage(Message msg) { 85 // Note: This is the message handler for the WebCore 86 // thread. 87 switch (msg.what) { 88 case OPEN: 89 nativeOpen((String) msg.obj); 90 break; 91 92 case CLOSE: 93 nativeClose(); 94 break; 95 96 case REMOVE_ALL: 97 nativeRemoveAllIcons(); 98 break; 99 100 case REQUEST_ICON: 101 IconListener l = (IconListener) msg.obj; 102 String url = msg.getData().getString("url"); 103 Bitmap icon = nativeIconForPageUrl(url); 104 if (icon != null) { 105 EventHandler.this.sendMessage( 106 Message.obtain(null, ICON_RESULT, 107 new IconResult(url, icon, l))); 108 } 109 break; 110 111 case RETAIN_ICON: 112 nativeRetainIconForPageUrl((String) msg.obj); 113 break; 114 115 case RELEASE_ICON: 116 nativeReleaseIconForPageUrl((String) msg.obj); 117 break; 118 } 119 } 120 }; 121 // Transfer all pending messages 122 for (int size = mMessages.size(); size > 0; size--) { 123 mHandler.sendMessage(mMessages.remove(0)); 124 } 125 mMessages = null; 126 } 127 } 128 129 private synchronized void postMessage(Message msg) { 130 if (mMessages != null) { 131 mMessages.add(msg); 132 } else { 133 mHandler.sendMessage(msg); 134 } 135 } 136 } 137 138 /** 139 * Interface for receiving icons from the database. 140 */ 141 public interface IconListener { 142 /** 143 * Called when the icon has been retrieved from the database and the 144 * result is non-null. 145 * @param url The url passed in the request. 146 * @param icon The favicon for the given url. 147 */ 148 public void onReceivedIcon(String url, Bitmap icon); 149 } 150 151 /** 152 * Open a the icon database and store the icons in the given path. 153 * @param path The directory path where the icon database will be stored. 154 * @return True if the database was successfully opened or created in 155 * the given path. 156 */ 157 public void open(String path) { 158 if (path != null) { 159 mEventHandler.postMessage( 160 Message.obtain(null, EventHandler.OPEN, path)); 161 } 162 } 163 164 /** 165 * Close the shared instance of the icon database. 166 */ 167 public void close() { 168 mEventHandler.postMessage( 169 Message.obtain(null, EventHandler.CLOSE)); 170 } 171 172 /** 173 * Removes all the icons in the database. 174 */ 175 public void removeAllIcons() { 176 mEventHandler.postMessage( 177 Message.obtain(null, EventHandler.REMOVE_ALL)); 178 } 179 180 /** 181 * Request the Bitmap representing the icon for the given page 182 * url. If the icon exists, the listener will be called with the result. 183 * @param url The page's url. 184 * @param listener An implementation on IconListener to receive the result. 185 */ 186 public void requestIconForPageUrl(String url, IconListener listener) { 187 if (listener == null || url == null) { 188 return; 189 } 190 Message msg = Message.obtain(null, EventHandler.REQUEST_ICON, listener); 191 msg.getData().putString("url", url); 192 mEventHandler.postMessage(msg); 193 } 194 195 /** 196 * Retain the icon for the given page url. 197 * @param url The page's url. 198 */ 199 public void retainIconForPageUrl(String url) { 200 if (url != null) { 201 mEventHandler.postMessage( 202 Message.obtain(null, EventHandler.RETAIN_ICON, url)); 203 } 204 } 205 206 /** 207 * Release the icon for the given page url. 208 * @param url The page's url. 209 */ 210 public void releaseIconForPageUrl(String url) { 211 if (url != null) { 212 mEventHandler.postMessage( 213 Message.obtain(null, EventHandler.RELEASE_ICON, url)); 214 } 215 } 216 217 /** 218 * Get the global instance of WebIconDatabase. 219 * @return A single instance of WebIconDatabase. It will be the same 220 * instance for the current process each time this method is 221 * called. 222 */ 223 public static WebIconDatabase getInstance() { 224 // XXX: Must be created in the UI thread. 225 if (sIconDatabase == null) { 226 sIconDatabase = new WebIconDatabase(); 227 } 228 return sIconDatabase; 229 } 230 231 /** 232 * Create the internal handler and transfer all pending messages. 233 * XXX: Called by WebCore thread only! 234 */ 235 /*package*/ void createHandler() { 236 mEventHandler.createHandler(); 237 } 238 239 /** 240 * Private constructor to avoid anyone else creating an instance. 241 */ 242 private WebIconDatabase() {} 243 244 // Native functions 245 private static native void nativeOpen(String path); 246 private static native void nativeClose(); 247 private static native void nativeRemoveAllIcons(); 248 private static native Bitmap nativeIconForPageUrl(String url); 249 private static native void nativeRetainIconForPageUrl(String url); 250 private static native void nativeReleaseIconForPageUrl(String url); 251} 252