diff options
| author | Jonathan Dixon <joth@google.com> | 2012-04-12 20:51:51 +0100 |
|---|---|---|
| committer | Jonathan Dixon <joth@google.com> | 2012-04-23 12:43:02 +0100 |
| commit | d3101b1d300f5942fdb7dfa323dc8830c4edc007 (patch) | |
| tree | 4140cbc09c362fd7584fec4f87dff13a79b22388 /core/java/android/webkit/WebIconDatabaseClassic.java | |
| parent | eb65757d24a97450fed160d66e86a4a62c392c5c (diff) | |
Seperate interface and implementation of 4 WebView classes
GeolocationPermissionsClassic
CookieManagerClassic
WebIconDatabaseClassic
WebStorageClassic
Also creats a WebViewFactory top level class - this remains hidden
for now, as it's currently only used implicitly by the other
public WebView classes to create the provider instances.
Bug: 5626244
Change-Id: Id0ca1c16d8058f31a86414bbc0e8a55db4b907ba
Diffstat (limited to 'core/java/android/webkit/WebIconDatabaseClassic.java')
| -rw-r--r-- | core/java/android/webkit/WebIconDatabaseClassic.java | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/core/java/android/webkit/WebIconDatabaseClassic.java b/core/java/android/webkit/WebIconDatabaseClassic.java new file mode 100644 index 000000000000..d6c4c3374893 --- /dev/null +++ b/core/java/android/webkit/WebIconDatabaseClassic.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.os.Handler; +import android.os.Message; +import android.provider.Browser; +import android.util.Log; + +import java.io.File; +import java.util.HashMap; +import java.util.Vector; + +class WebIconDatabaseClassic extends WebIconDatabase { + private static final String LOGTAG = "WebIconDatabase"; + // Global instance of a WebIconDatabase + private static WebIconDatabaseClassic sIconDatabase; + // EventHandler for handling messages before and after the WebCore thread is + // ready. + private final EventHandler mEventHandler = new EventHandler(); + + // Class to handle messages before WebCore is ready + private static class EventHandler extends Handler { + // Message ids + static final int OPEN = 0; + static final int CLOSE = 1; + static final int REMOVE_ALL = 2; + static final int REQUEST_ICON = 3; + static final int RETAIN_ICON = 4; + static final int RELEASE_ICON = 5; + static final int BULK_REQUEST_ICON = 6; + // Message for dispatching icon request results + private static final int ICON_RESULT = 10; + // Actual handler that runs in WebCore thread + private Handler mHandler; + // Vector of messages before the WebCore thread is ready + private Vector<Message> mMessages = new Vector<Message>(); + // Class to handle a result dispatch + private class IconResult { + private final String mUrl; + private final Bitmap mIcon; + private final IconListener mListener; + IconResult(String url, Bitmap icon, IconListener l) { + mUrl = url; + mIcon = icon; + mListener = l; + } + void dispatch() { + mListener.onReceivedIcon(mUrl, mIcon); + } + } + + @Override + public void handleMessage(Message msg) { + // Note: This is the message handler for the UI thread. + switch (msg.what) { + case ICON_RESULT: + ((IconResult) msg.obj).dispatch(); + break; + } + } + + // Called by WebCore thread to create the actual handler + private synchronized void createHandler() { + if (mHandler == null) { + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + // Note: This is the message handler for the WebCore + // thread. + switch (msg.what) { + case OPEN: + nativeOpen((String) msg.obj); + break; + + case CLOSE: + nativeClose(); + break; + + case REMOVE_ALL: + nativeRemoveAllIcons(); + break; + + case REQUEST_ICON: + IconListener l = (IconListener) msg.obj; + String url = msg.getData().getString("url"); + requestIconAndSendResult(url, l); + break; + + case BULK_REQUEST_ICON: + bulkRequestIcons(msg); + break; + + case RETAIN_ICON: + nativeRetainIconForPageUrl((String) msg.obj); + break; + + case RELEASE_ICON: + nativeReleaseIconForPageUrl((String) msg.obj); + break; + } + } + }; + // Transfer all pending messages + for (int size = mMessages.size(); size > 0; size--) { + mHandler.sendMessage(mMessages.remove(0)); + } + mMessages = null; + } + } + + private synchronized boolean hasHandler() { + return mHandler != null; + } + + private synchronized void postMessage(Message msg) { + if (mMessages != null) { + mMessages.add(msg); + } else { + mHandler.sendMessage(msg); + } + } + + private void bulkRequestIcons(Message msg) { + HashMap map = (HashMap) msg.obj; + IconListener listener = (IconListener) map.get("listener"); + ContentResolver cr = (ContentResolver) map.get("contentResolver"); + String where = (String) map.get("where"); + + Cursor c = null; + try { + c = cr.query( + Browser.BOOKMARKS_URI, + new String[] { Browser.BookmarkColumns.URL }, + where, null, null); + if (c.moveToFirst()) { + do { + String url = c.getString(0); + requestIconAndSendResult(url, listener); + } while (c.moveToNext()); + } + } catch (IllegalStateException e) { + Log.e(LOGTAG, "BulkRequestIcons", e); + } finally { + if (c != null) c.close(); + } + } + + private void requestIconAndSendResult(String url, IconListener listener) { + Bitmap icon = nativeIconForPageUrl(url); + if (icon != null) { + sendMessage(obtainMessage(ICON_RESULT, + new IconResult(url, icon, listener))); + } + } + } + + @Override + public void open(String path) { + if (path != null) { + // Make the directories and parents if they don't exist + File db = new File(path); + if (!db.exists()) { + db.mkdirs(); + } + mEventHandler.postMessage( + Message.obtain(null, EventHandler.OPEN, db.getAbsolutePath())); + } + } + + @Override + public void close() { + mEventHandler.postMessage( + Message.obtain(null, EventHandler.CLOSE)); + } + + @Override + public void removeAllIcons() { + mEventHandler.postMessage( + Message.obtain(null, EventHandler.REMOVE_ALL)); + } + + /** + * Request the Bitmap representing the icon for the given page + * url. If the icon exists, the listener will be called with the result. + * @param url The page's url. + * @param listener An implementation on IconListener to receive the result. + */ + public void requestIconForPageUrl(String url, IconListener listener) { + if (listener == null || url == null) { + return; + } + Message msg = Message.obtain(null, EventHandler.REQUEST_ICON, listener); + msg.getData().putString("url", url); + mEventHandler.postMessage(msg); + } + + /** {@hide} + */ + public void bulkRequestIconForPageUrl(ContentResolver cr, String where, + IconListener listener) { + if (listener == null) { + return; + } + + // Special case situation: we don't want to add this message to the + // queue if there is no handler because we may never have a real + // handler to service the messages and the cursor will never get + // closed. + if (mEventHandler.hasHandler()) { + // Don't use Bundle as it is parcelable. + HashMap<String, Object> map = new HashMap<String, Object>(); + map.put("contentResolver", cr); + map.put("where", where); + map.put("listener", listener); + Message msg = + Message.obtain(null, EventHandler.BULK_REQUEST_ICON, map); + mEventHandler.postMessage(msg); + } + } + + @Override + public void retainIconForPageUrl(String url) { + if (url != null) { + mEventHandler.postMessage( + Message.obtain(null, EventHandler.RETAIN_ICON, url)); + } + } + + @Override + public void releaseIconForPageUrl(String url) { + if (url != null) { + mEventHandler.postMessage( + Message.obtain(null, EventHandler.RELEASE_ICON, url)); + } + } + + /** + * Get the global instance of WebIconDatabase. + * @return A single instance of WebIconDatabase. It will be the same + * instance for the current process each time this method is + * called. + */ + public static WebIconDatabaseClassic getInstance() { + // XXX: Must be created in the UI thread. + if (sIconDatabase == null) { + sIconDatabase = new WebIconDatabaseClassic(); + } + return sIconDatabase; + } + + /** + * Create the internal handler and transfer all pending messages. + * XXX: Called by WebCore thread only! + */ + /*package*/ void createHandler() { + mEventHandler.createHandler(); + } + + /** + * Private constructor to avoid anyone else creating an instance. + */ + private WebIconDatabaseClassic() {} + + // Native functions + private static native void nativeOpen(String path); + private static native void nativeClose(); + private static native void nativeRemoveAllIcons(); + private static native Bitmap nativeIconForPageUrl(String url); + private static native void nativeRetainIconForPageUrl(String url); + private static native void nativeReleaseIconForPageUrl(String url); +} |
