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 | |
parent | eb65757d24a97450fed160d66e86a4a62c392c5c (diff) | |
download | frameworks_base-d3101b1d300f5942fdb7dfa323dc8830c4edc007.zip frameworks_base-d3101b1d300f5942fdb7dfa323dc8830c4edc007.tar.gz frameworks_base-d3101b1d300f5942fdb7dfa323dc8830c4edc007.tar.bz2 |
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
17 files changed, 1302 insertions, 879 deletions
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java index 2997c1a..825436f 100644 --- a/core/java/android/webkit/CookieManager.java +++ b/core/java/android/webkit/CookieManager.java @@ -16,27 +16,20 @@ package android.webkit; -import android.net.ParseException; import android.net.WebAddress; -import android.os.AsyncTask; -import android.util.Log; - /** * Manages the cookies used by an application's {@link WebView} instances. * Cookies are manipulated according to RFC2109. */ public class CookieManager { - - private static CookieManager sRef; - - private static final String LOGTAG = "webkit"; - - private int mPendingCookieOperations = 0; - - private CookieManager() { + /** + * @hide Only for use by WebViewProvider implementations + */ + protected CookieManager() { } + @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException("doesn't implement Cloneable"); } @@ -46,14 +39,11 @@ public class CookieManager { * before the application instantiates a {@link WebView} instance, * {@link CookieSyncManager#createInstance(Context)} must be called * first. - * + * * @return The singleton CookieManager instance */ public static synchronized CookieManager getInstance() { - if (sRef == null) { - sRef = new CookieManager(); - } - return sRef; + return WebViewFactory.getProvider().getCookieManager(); } /** @@ -63,7 +53,7 @@ public class CookieManager { * cookies */ public synchronized void setAcceptCookie(boolean accept) { - nativeSetAcceptCookie(accept); + throw new MustOverrideException(); } /** @@ -72,39 +62,20 @@ public class CookieManager { * @return True if {@link WebView} instances send and accept cookies */ public synchronized boolean acceptCookie() { - return nativeAcceptCookie(); + throw new MustOverrideException(); } - /** + /** * Sets a cookie for the given URL. Any existing cookie with the same host, * path and name will be replaced with the new cookie. The cookie being set * must not have expired and must not be a session cookie, otherwise it * will be ignored. * @param url The URL for which the cookie is set - * @param value The cookie as a string, using the format of the - * 'Set-Cookie' HTTP response header + * @param value The cookie as a string, using the format of the 'Set-Cookie' + * HTTP response header */ public void setCookie(String url, String value) { - setCookie(url, value, false); - } - - /** - * See {@link setCookie(String, String)} - * @param url The URL for which the cookie is set - * @param value The value of the cookie, as a string, using the format of - * the 'Set-Cookie' HTTP response header - * @param privateBrowsing Whether to use the private browsing cookie jar - */ - void setCookie(String url, String value, boolean privateBrowsing) { - WebAddress uri; - try { - uri = new WebAddress(url); - } catch (ParseException ex) { - Log.e(LOGTAG, "Bad address: " + url); - return; - } - - nativeSetCookie(uri.toString(), value, privateBrowsing); + throw new MustOverrideException(); } /** @@ -114,11 +85,11 @@ public class CookieManager { * HTTP request header */ public String getCookie(String url) { - return getCookie(url, false); + throw new MustOverrideException(); } /** - * See {@link getCookie(String)} + * See {@link #getCookie(String)} * @param url The URL for which the cookies are requested * @param privateBrowsing Whether to use the private browsing cookie jar * @return value The cookies as a string, using the format of the 'Cookie' @@ -126,15 +97,7 @@ public class CookieManager { * @hide Used by Browser, no intention to publish. */ public String getCookie(String url, boolean privateBrowsing) { - WebAddress uri; - try { - uri = new WebAddress(url); - } catch (ParseException ex) { - Log.e(LOGTAG, "Bad address: " + url); - return null; - } - - return nativeGetCookie(uri.toString(), privateBrowsing); + throw new MustOverrideException(); } /** @@ -146,32 +109,7 @@ public class CookieManager { * @hide Used by RequestHandle, no intention to publish. */ public synchronized String getCookie(WebAddress uri) { - return nativeGetCookie(uri.toString(), false); - } - - /** - * Waits for pending operations to completed. - */ - void waitForCookieOperationsToComplete() { - // Note that this function is applicable for both the java - // and native http stacks, and works correctly with either. - synchronized (this) { - while (mPendingCookieOperations > 0) { - try { - wait(); - } catch (InterruptedException e) { } - } - } - } - - private synchronized void signalCookieOperationsComplete() { - mPendingCookieOperations--; - assert mPendingCookieOperations > -1; - notify(); - } - - private synchronized void signalCookieOperationsStart() { - mPendingCookieOperations++; + throw new MustOverrideException(); } /** @@ -179,21 +117,14 @@ public class CookieManager { * date. */ public void removeSessionCookie() { - signalCookieOperationsStart(); - new AsyncTask<Void, Void, Void>() { - protected Void doInBackground(Void... none) { - nativeRemoveSessionCookie(); - signalCookieOperationsComplete(); - return null; - } - }.execute(); + throw new MustOverrideException(); } /** * Removes all cookies. */ public void removeAllCookie() { - nativeRemoveAllCookie(); + throw new MustOverrideException(); } /** @@ -201,32 +132,32 @@ public class CookieManager { * @return True if there are stored cookies. */ public synchronized boolean hasCookies() { - return hasCookies(false); + throw new MustOverrideException(); } /** - * See {@link hasCookies()}. + * See {@link #hasCookies()}. * @param privateBrowsing Whether to use the private browsing cookie jar * @hide Used by Browser, no intention to publish. */ public synchronized boolean hasCookies(boolean privateBrowsing) { - return nativeHasCookies(privateBrowsing); + throw new MustOverrideException(); } /** * Removes all expired cookies. */ public void removeExpiredCookie() { - nativeRemoveExpiredCookie(); + throw new MustOverrideException(); } /** - * Package level api, called from CookieSyncManager - * * Flush all cookies managed by the Chrome HTTP stack to flash. + * + * @hide Package level api, called from CookieSyncManager */ - void flushCookieStore() { - nativeFlushCookieStore(); + protected void flushCookieStore() { + throw new MustOverrideException(); } /** @@ -236,7 +167,7 @@ public class CookieManager { * file scheme URLs */ public static boolean allowFileSchemeCookies() { - return nativeAcceptFileSchemeCookies(); + throw new MustOverrideException(); } /** @@ -250,19 +181,6 @@ public class CookieManager { * {@link WebView} or CookieManager instance has been created. */ public static void setAcceptFileSchemeCookies(boolean accept) { - nativeSetAcceptFileSchemeCookies(accept); + throw new MustOverrideException(); } - - // Native functions - private static native boolean nativeAcceptCookie(); - private static native String nativeGetCookie(String url, boolean privateBrowsing); - private static native boolean nativeHasCookies(boolean privateBrowsing); - private static native void nativeRemoveAllCookie(); - private static native void nativeRemoveExpiredCookie(); - private static native void nativeRemoveSessionCookie(); - private static native void nativeSetAcceptCookie(boolean accept); - private static native void nativeSetCookie(String url, String value, boolean privateBrowsing); - private static native void nativeFlushCookieStore(); - private static native boolean nativeAcceptFileSchemeCookies(); - private static native void nativeSetAcceptFileSchemeCookies(boolean accept); } diff --git a/core/java/android/webkit/CookieManagerClassic.java b/core/java/android/webkit/CookieManagerClassic.java new file mode 100644 index 0000000..f1aebcf --- /dev/null +++ b/core/java/android/webkit/CookieManagerClassic.java @@ -0,0 +1,198 @@ +/* + * 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.net.ParseException; +import android.net.WebAddress; +import android.os.AsyncTask; +import android.util.Log; + +class CookieManagerClassic extends CookieManager { + + private static CookieManagerClassic sRef; + + private static final String LOGTAG = "webkit"; + + private int mPendingCookieOperations = 0; + + private CookieManagerClassic() { + } + + public static synchronized CookieManagerClassic getInstance() { + if (sRef == null) { + sRef = new CookieManagerClassic(); + } + return sRef; + } + + @Override + public synchronized void setAcceptCookie(boolean accept) { + nativeSetAcceptCookie(accept); + } + + @Override + public synchronized boolean acceptCookie() { + return nativeAcceptCookie(); + } + + @Override + public void setCookie(String url, String value) { + setCookie(url, value, false); + } + + /** + * See {@link #setCookie(String, String)} + * @param url The URL for which the cookie is set + * @param value The value of the cookie, as a string, using the format of + * the 'Set-Cookie' HTTP response header + * @param privateBrowsing Whether to use the private browsing cookie jar + */ + void setCookie(String url, String value, boolean privateBrowsing) { + WebAddress uri; + try { + uri = new WebAddress(url); + } catch (ParseException ex) { + Log.e(LOGTAG, "Bad address: " + url); + return; + } + + nativeSetCookie(uri.toString(), value, privateBrowsing); + } + + @Override + public String getCookie(String url) { + return getCookie(url, false); + } + + @Override + public String getCookie(String url, boolean privateBrowsing) { + WebAddress uri; + try { + uri = new WebAddress(url); + } catch (ParseException ex) { + Log.e(LOGTAG, "Bad address: " + url); + return null; + } + + return nativeGetCookie(uri.toString(), privateBrowsing); + } + + @Override + public synchronized String getCookie(WebAddress uri) { + return nativeGetCookie(uri.toString(), false); + } + + /** + * Waits for pending operations to completed. + */ + void waitForCookieOperationsToComplete() { + // Note that this function is applicable for both the java + // and native http stacks, and works correctly with either. + synchronized (this) { + while (mPendingCookieOperations > 0) { + try { + wait(); + } catch (InterruptedException e) { } + } + } + } + + private synchronized void signalCookieOperationsComplete() { + mPendingCookieOperations--; + assert mPendingCookieOperations > -1; + notify(); + } + + private synchronized void signalCookieOperationsStart() { + mPendingCookieOperations++; + } + + @Override + public void removeSessionCookie() { + signalCookieOperationsStart(); + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... none) { + nativeRemoveSessionCookie(); + signalCookieOperationsComplete(); + return null; + } + }.execute(); + } + + @Override + public void removeAllCookie() { + nativeRemoveAllCookie(); + } + + @Override + public synchronized boolean hasCookies() { + return hasCookies(false); + } + + @Override + public synchronized boolean hasCookies(boolean privateBrowsing) { + return nativeHasCookies(privateBrowsing); + } + + @Override + public void removeExpiredCookie() { + nativeRemoveExpiredCookie(); + } + + @Override + protected void flushCookieStore() { + nativeFlushCookieStore(); + } + + /** + * Gets whether the application's {@link WebView} instances send and accept + * cookies for file scheme URLs. + * @return True if {@link WebView} instances send and accept cookies for + * file scheme URLs + */ + public static boolean allowFileSchemeCookies() { + return nativeAcceptFileSchemeCookies(); + } + + /** + * Sets whether the application's {@link WebView} instances should send and + * accept cookies for file scheme URLs. + * Use of cookies with file scheme URLs is potentially insecure. Do not use + * this feature unless you can be sure that no unintentional sharing of + * cookie data can take place. + * <p> + * Note that calls to this method will have no effect if made after a + * {@link WebView} or CookieManager instance has been created. + */ + public static void setAcceptFileSchemeCookies(boolean accept) { + nativeSetAcceptFileSchemeCookies(accept); + } + + // Native functions + private static native boolean nativeAcceptCookie(); + private static native String nativeGetCookie(String url, boolean privateBrowsing); + private static native boolean nativeHasCookies(boolean privateBrowsing); + private static native void nativeRemoveAllCookie(); + private static native void nativeRemoveExpiredCookie(); + private static native void nativeRemoveSessionCookie(); + private static native void nativeSetAcceptCookie(boolean accept); + private static native void nativeSetCookie(String url, String value, boolean privateBrowsing); + private static native void nativeFlushCookieStore(); + private static native boolean nativeAcceptFileSchemeCookies(); + private static native void nativeSetAcceptFileSchemeCookies(boolean accept); +} diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java index a916884..cd5c9d1 100755 --- a/core/java/android/webkit/GeolocationPermissions.java +++ b/core/java/android/webkit/GeolocationPermissions.java @@ -16,13 +16,7 @@ package android.webkit; -import android.os.Handler; -import android.os.Message; - -import java.util.HashMap; -import java.util.Map; import java.util.Set; -import java.util.Vector; /** * This class is used to manage permissions for the WebView's Geolocation @@ -44,9 +38,6 @@ import java.util.Vector; * The methods of this class can be used to modify and interrogate the stored * Geolocation permissions at any time. */ -// This class is the Java counterpart of the WebKit C++ GeolocationPermissions -// class. It simply marshals calls from the UI thread to the WebKit thread. -// // Within WebKit, Geolocation permissions may be applied either temporarily // (for the duration of the page) or permanently. This class deals only with // permanent permissions. @@ -68,144 +59,12 @@ public class GeolocationPermissions { public void invoke(String origin, boolean allow, boolean retain); }; - // Global instance - private static GeolocationPermissions sInstance; - - private Handler mHandler; - private Handler mUIHandler; - - // A queue to store messages until the handler is ready. - private Vector<Message> mQueuedMessages; - - // Message ids - static final int GET_ORIGINS = 0; - static final int GET_ALLOWED = 1; - static final int CLEAR = 2; - static final int ALLOW = 3; - static final int CLEAR_ALL = 4; - - // Message ids on the UI thread - static final int RETURN_ORIGINS = 0; - static final int RETURN_ALLOWED = 1; - - private static final String ORIGINS = "origins"; - private static final String ORIGIN = "origin"; - private static final String CALLBACK = "callback"; - private static final String ALLOWED = "allowed"; - /** * Get the singleton instance of this class. * @return The singleton {@link GeolocationPermissions} instance. */ public static GeolocationPermissions getInstance() { - if (sInstance == null) { - sInstance = new GeolocationPermissions(); - } - return sInstance; - } - - /** - * Creates the UI message handler. Must be called on the UI thread. - * @hide - */ - public void createUIHandler() { - if (mUIHandler == null) { - mUIHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - // Runs on the UI thread. - switch (msg.what) { - case RETURN_ORIGINS: { - Map values = (Map) msg.obj; - Set<String> origins = (Set<String>) values.get(ORIGINS); - ValueCallback<Set<String> > callback = (ValueCallback<Set<String> >) values.get(CALLBACK); - callback.onReceiveValue(origins); - } break; - case RETURN_ALLOWED: { - Map values = (Map) msg.obj; - Boolean allowed = (Boolean) values.get(ALLOWED); - ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK); - callback.onReceiveValue(allowed); - } break; - } - } - }; - } - } - - /** - * Creates the message handler. Must be called on the WebKit thread. - * @hide - */ - public synchronized void createHandler() { - if (mHandler == null) { - mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - // Runs on the WebKit thread. - switch (msg.what) { - case GET_ORIGINS: { - Set origins = nativeGetOrigins(); - ValueCallback callback = (ValueCallback) msg.obj; - Map values = new HashMap<String, Object>(); - values.put(CALLBACK, callback); - values.put(ORIGINS, origins); - postUIMessage(Message.obtain(null, RETURN_ORIGINS, values)); - } break; - case GET_ALLOWED: { - Map values = (Map) msg.obj; - String origin = (String) values.get(ORIGIN); - ValueCallback callback = (ValueCallback) values.get(CALLBACK); - boolean allowed = nativeGetAllowed(origin); - Map retValues = new HashMap<String, Object>(); - retValues.put(CALLBACK, callback); - retValues.put(ALLOWED, Boolean.valueOf(allowed)); - postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues)); - } break; - case CLEAR: - nativeClear((String) msg.obj); - break; - case ALLOW: - nativeAllow((String) msg.obj); - break; - case CLEAR_ALL: - nativeClearAll(); - break; - } - } - }; - - // Handle the queued messages - if (mQueuedMessages != null) { - while (!mQueuedMessages.isEmpty()) { - mHandler.sendMessage(mQueuedMessages.remove(0)); - } - mQueuedMessages = null; - } - } - } - - /** - * Utility function to send a message to our handler. - */ - private synchronized void postMessage(Message msg) { - if (mHandler == null) { - if (mQueuedMessages == null) { - mQueuedMessages = new Vector<Message>(); - } - mQueuedMessages.add(msg); - } else { - mHandler.sendMessage(msg); - } - } - - /** - * Utility function to send a message to the handler on the UI thread - */ - private void postUIMessage(Message msg) { - if (mUIHandler != null) { - mUIHandler.sendMessage(msg); - } + return WebViewFactory.getProvider().getGeolocationPermissions(); } /** @@ -222,14 +81,7 @@ public class GeolocationPermissions { // (Database, Geolocation etc) do so, it's safe to match up origins based // on this string. public void getOrigins(ValueCallback<Set<String> > callback) { - if (callback != null) { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - Set origins = nativeGetOrigins(); - callback.onReceiveValue(origins); - } else { - postMessage(Message.obtain(null, GET_ORIGINS, callback)); - } - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -243,54 +95,30 @@ public class GeolocationPermissions { * Geolocation API. */ public void getAllowed(String origin, ValueCallback<Boolean> callback) { - if (callback == null) { - return; - } - if (origin == null) { - callback.onReceiveValue(null); - return; - } - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - boolean allowed = nativeGetAllowed(origin); - callback.onReceiveValue(Boolean.valueOf(allowed)); - } else { - Map values = new HashMap<String, Object>(); - values.put(ORIGIN, origin); - values.put(CALLBACK, callback); - postMessage(Message.obtain(null, GET_ALLOWED, values)); - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** * Clear the Geolocation permission state for the specified origin. * @param origin The origin for which Geolocation permissions are cleared. */ - // This method may be called before the WebKit - // thread has intialized the message handler. Messages will be queued until - // this time. public void clear(String origin) { - // Called on the UI thread. - postMessage(Message.obtain(null, CLEAR, origin)); + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** * Allow the specified origin to use the Geolocation API. * @param origin The origin for which Geolocation API use is allowed. */ - // This method may be called before the WebKit - // thread has intialized the message handler. Messages will be queued until - // this time. public void allow(String origin) { - // Called on the UI thread. - postMessage(Message.obtain(null, ALLOW, origin)); + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** * Clear the Geolocation permission state for all origins. */ public void clearAll() { - // Called on the UI thread. - postMessage(Message.obtain(null, CLEAR_ALL)); + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -299,14 +127,7 @@ public class GeolocationPermissions { * Note this constructor was erroneously public and published in SDK levels prior to 16, but * applications using it would receive a non-functional instance of this class (there was no * way to call createHandler() and createUIHandler(), so it would not work). - * @hide + * @hide Only for use by WebViewProvider implementations */ public GeolocationPermissions() {} - - // Native functions, run on the WebKit thread. - private static native Set nativeGetOrigins(); - private static native boolean nativeGetAllowed(String origin); - private static native void nativeClear(String origin); - private static native void nativeAllow(String origin); - private static native void nativeClearAll(); } diff --git a/core/java/android/webkit/GeolocationPermissionsClassic.java b/core/java/android/webkit/GeolocationPermissionsClassic.java new file mode 100755 index 0000000..8a9df39 --- /dev/null +++ b/core/java/android/webkit/GeolocationPermissionsClassic.java @@ -0,0 +1,234 @@ +/* + * 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.os.Handler; +import android.os.Message; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +// This class is the Java counterpart of the WebKit C++ GeolocationPermissions +// class. It simply marshals calls from the UI thread to the WebKit thread. +final class GeolocationPermissionsClassic extends GeolocationPermissions { + private Handler mHandler; + private Handler mUIHandler; + + // A queue to store messages until the handler is ready. + private Vector<Message> mQueuedMessages; + + // Message ids + static final int GET_ORIGINS = 0; + static final int GET_ALLOWED = 1; + static final int CLEAR = 2; + static final int ALLOW = 3; + static final int CLEAR_ALL = 4; + + // Message ids on the UI thread + static final int RETURN_ORIGINS = 0; + static final int RETURN_ALLOWED = 1; + + private static final String ORIGINS = "origins"; + private static final String ORIGIN = "origin"; + private static final String CALLBACK = "callback"; + private static final String ALLOWED = "allowed"; + + // Global instance + private static GeolocationPermissionsClassic sInstance; + + public static GeolocationPermissionsClassic getInstance() { + if (sInstance == null) { + sInstance = new GeolocationPermissionsClassic(); + } + return sInstance; + } + + /** + * Creates the UI message handler. Must be called on the UI thread. + * @hide + */ + public void createUIHandler() { + if (mUIHandler == null) { + mUIHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + // Runs on the UI thread. + switch (msg.what) { + case RETURN_ORIGINS: { + Map values = (Map) msg.obj; + Set<String> origins = (Set<String>) values.get(ORIGINS); + ValueCallback<Set<String> > callback = (ValueCallback<Set<String> >) values.get(CALLBACK); + callback.onReceiveValue(origins); + } break; + case RETURN_ALLOWED: { + Map values = (Map) msg.obj; + Boolean allowed = (Boolean) values.get(ALLOWED); + ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK); + callback.onReceiveValue(allowed); + } break; + } + } + }; + } + } + + /** + * Creates the message handler. Must be called on the WebKit thread. + * @hide + */ + public synchronized void createHandler() { + if (mHandler == null) { + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + // Runs on the WebKit thread. + switch (msg.what) { + case GET_ORIGINS: { + Set origins = nativeGetOrigins(); + ValueCallback callback = (ValueCallback) msg.obj; + Map values = new HashMap<String, Object>(); + values.put(CALLBACK, callback); + values.put(ORIGINS, origins); + postUIMessage(Message.obtain(null, RETURN_ORIGINS, values)); + } break; + case GET_ALLOWED: { + Map values = (Map) msg.obj; + String origin = (String) values.get(ORIGIN); + ValueCallback callback = (ValueCallback) values.get(CALLBACK); + boolean allowed = nativeGetAllowed(origin); + Map retValues = new HashMap<String, Object>(); + retValues.put(CALLBACK, callback); + retValues.put(ALLOWED, Boolean.valueOf(allowed)); + postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues)); + } break; + case CLEAR: + nativeClear((String) msg.obj); + break; + case ALLOW: + nativeAllow((String) msg.obj); + break; + case CLEAR_ALL: + nativeClearAll(); + break; + } + } + }; + + // Handle the queued messages + if (mQueuedMessages != null) { + while (!mQueuedMessages.isEmpty()) { + mHandler.sendMessage(mQueuedMessages.remove(0)); + } + mQueuedMessages = null; + } + } + } + + /** + * Utility function to send a message to our handler. + */ + private synchronized void postMessage(Message msg) { + if (mHandler == null) { + if (mQueuedMessages == null) { + mQueuedMessages = new Vector<Message>(); + } + mQueuedMessages.add(msg); + } else { + mHandler.sendMessage(msg); + } + } + + /** + * Utility function to send a message to the handler on the UI thread + */ + private void postUIMessage(Message msg) { + if (mUIHandler != null) { + mUIHandler.sendMessage(msg); + } + } + + // Note that we represent the origins as strings. These are created using + // WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules' + // (Database, Geolocation etc) do so, it's safe to match up origins based + // on this string. + @Override + public void getOrigins(ValueCallback<Set<String> > callback) { + if (callback != null) { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + Set origins = nativeGetOrigins(); + callback.onReceiveValue(origins); + } else { + postMessage(Message.obtain(null, GET_ORIGINS, callback)); + } + } + } + + @Override + public void getAllowed(String origin, ValueCallback<Boolean> callback) { + if (callback == null) { + return; + } + if (origin == null) { + callback.onReceiveValue(null); + return; + } + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + boolean allowed = nativeGetAllowed(origin); + callback.onReceiveValue(Boolean.valueOf(allowed)); + } else { + Map values = new HashMap<String, Object>(); + values.put(ORIGIN, origin); + values.put(CALLBACK, callback); + postMessage(Message.obtain(null, GET_ALLOWED, values)); + } + } + + // This method may be called before the WebKit + // thread has intialized the message handler. Messages will be queued until + // this time. + @Override + public void clear(String origin) { + // Called on the UI thread. + postMessage(Message.obtain(null, CLEAR, origin)); + } + + // This method may be called before the WebKit + // thread has intialized the message handler. Messages will be queued until + // this time. + @Override + public void allow(String origin) { + // Called on the UI thread. + postMessage(Message.obtain(null, ALLOW, origin)); + } + + @Override + public void clearAll() { + // Called on the UI thread. + postMessage(Message.obtain(null, CLEAR_ALL)); + } + + GeolocationPermissionsClassic() {} + + // Native functions, run on the WebKit thread. + private static native Set nativeGetOrigins(); + private static native boolean nativeGetAllowed(String origin); + private static native void nativeClear(String origin); + private static native void nativeAllow(String origin); + private static native void nativeClearAll(); +} diff --git a/core/java/android/webkit/MustOverrideException.java b/core/java/android/webkit/MustOverrideException.java new file mode 100644 index 0000000..0643bf0 --- /dev/null +++ b/core/java/android/webkit/MustOverrideException.java @@ -0,0 +1,25 @@ +/* + * 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; + +// TODO: Remove MustOverrideException and make all methods throwing it abstract instead; +// needs API file update. +class MustOverrideException extends RuntimeException { + MustOverrideException() { + super("abstract function called: must be overriden!"); + } +}
\ No newline at end of file diff --git a/core/java/android/webkit/WebIconDatabase.java b/core/java/android/webkit/WebIconDatabase.java index 9299b71..99f20ff 100644 --- a/core/java/android/webkit/WebIconDatabase.java +++ b/core/java/android/webkit/WebIconDatabase.java @@ -17,16 +17,7 @@ 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; /** * Functions for manipulating the icon database used by WebView. @@ -36,149 +27,6 @@ import java.util.Vector; * single object. */ public class WebIconDatabase { - private static final String LOGTAG = "WebIconDatabase"; - // Global instance of a WebIconDatabase - private static WebIconDatabase 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))); - } - } - } - /** * Interface for receiving icons from the database. */ @@ -197,31 +45,21 @@ public class WebIconDatabase { * @param path The directory path where the icon database will be stored. */ 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())); - } + throw new MustOverrideException(); } /** * Close the shared instance of the icon database. */ public void close() { - mEventHandler.postMessage( - Message.obtain(null, EventHandler.CLOSE)); + throw new MustOverrideException(); } /** * Removes all the icons in the database. */ public void removeAllIcons() { - mEventHandler.postMessage( - Message.obtain(null, EventHandler.REMOVE_ALL)); + throw new MustOverrideException(); } /** @@ -231,36 +69,14 @@ public class WebIconDatabase { * @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); + throw new MustOverrideException(); } /** {@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); - } + throw new MustOverrideException(); } /** @@ -268,10 +84,7 @@ public class WebIconDatabase { * @param url The page's url. */ public void retainIconForPageUrl(String url) { - if (url != null) { - mEventHandler.postMessage( - Message.obtain(null, EventHandler.RETAIN_ICON, url)); - } + throw new MustOverrideException(); } /** @@ -279,10 +92,7 @@ public class WebIconDatabase { * @param url The page's url. */ public void releaseIconForPageUrl(String url) { - if (url != null) { - mEventHandler.postMessage( - Message.obtain(null, EventHandler.RELEASE_ICON, url)); - } + throw new MustOverrideException(); } /** @@ -293,30 +103,11 @@ public class WebIconDatabase { */ public static WebIconDatabase getInstance() { // XXX: Must be created in the UI thread. - if (sIconDatabase == null) { - sIconDatabase = new WebIconDatabase(); - } - return sIconDatabase; + return WebViewFactory.getProvider().getWebIconDatabase(); } /** - * Create the internal handler and transfer all pending messages. - * XXX: Called by WebCore thread only! + * @hide Only for use by WebViewProvider implementations */ - /*package*/ void createHandler() { - mEventHandler.createHandler(); - } - - /** - * Private constructor to avoid anyone else creating an instance. - */ - private WebIconDatabase() {} - - // 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); + protected WebIconDatabase() {} } diff --git a/core/java/android/webkit/WebIconDatabaseClassic.java b/core/java/android/webkit/WebIconDatabaseClassic.java new file mode 100644 index 0000000..d6c4c33 --- /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); +} diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 4cd828e..1bbf00f 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -27,18 +27,10 @@ import android.os.Build; * been destroyed, any method call on WebSettings will throw an * IllegalStateException. */ -// This is (effectively) an abstract base class; concrete WebViewProviders must +// This is an abstract base class: concrete WebViewProviders must // create a class derived from this, and return an instance of it in the // WebViewProvider.getWebSettingsProvider() method implementation. public abstract class WebSettings { - // TODO: Remove MustOverrideException and make all methods throwing it abstract instead; - // needs API file update. - private static class MustOverrideException extends RuntimeException { - MustOverrideException() { - super("abstract function called: must be overriden!"); - } - } - /** * Enum for controlling the layout of html. * NORMAL means no rendering changes. diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java index 041791b..c46d161 100644 --- a/core/java/android/webkit/WebStorage.java +++ b/core/java/android/webkit/WebStorage.java @@ -16,13 +16,7 @@ package android.webkit; -import android.os.Handler; -import android.os.Message; - -import java.util.Collection; -import java.util.HashMap; import java.util.Map; -import java.util.Set; /** * This class is used to manage the JavaScript storage APIs provided by the @@ -56,34 +50,6 @@ public class WebStorage { public void updateQuota(long newQuota); }; - // Global instance of a WebStorage - private static WebStorage sWebStorage; - - // Message ids - static final int UPDATE = 0; - static final int SET_QUOTA_ORIGIN = 1; - static final int DELETE_ORIGIN = 2; - static final int DELETE_ALL = 3; - static final int GET_ORIGINS = 4; - static final int GET_USAGE_ORIGIN = 5; - static final int GET_QUOTA_ORIGIN = 6; - - // Message ids on the UI thread - static final int RETURN_ORIGINS = 0; - static final int RETURN_USAGE_ORIGIN = 1; - static final int RETURN_QUOTA_ORIGIN = 2; - - private static final String ORIGINS = "origins"; - private static final String ORIGIN = "origin"; - private static final String CALLBACK = "callback"; - private static final String USAGE = "usage"; - private static final String QUOTA = "quota"; - - private Map <String, Origin> mOrigins; - - private Handler mHandler = null; - private Handler mUIHandler = null; - /** * This class encapsulates information about the amount of storage * currently used by an origin for the JavaScript storage APIs. @@ -94,18 +60,21 @@ public class WebStorage { private long mQuota = 0; private long mUsage = 0; - private Origin(String origin, long quota, long usage) { + /** @hide */ + protected Origin(String origin, long quota, long usage) { mOrigin = origin; mQuota = quota; mUsage = usage; } - private Origin(String origin, long quota) { + /** @hide */ + protected Origin(String origin, long quota) { mOrigin = origin; mQuota = quota; } - private Origin(String origin) { + /** @hide */ + protected Origin(String origin) { mOrigin = origin; } @@ -142,114 +111,6 @@ public class WebStorage { } } - /** - * Message handler, UI side - * @hide - */ - public void createUIHandler() { - if (mUIHandler == null) { - mUIHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case RETURN_ORIGINS: { - Map values = (Map) msg.obj; - Map origins = (Map) values.get(ORIGINS); - ValueCallback<Map> callback = (ValueCallback<Map>) values.get(CALLBACK); - callback.onReceiveValue(origins); - } break; - - case RETURN_USAGE_ORIGIN: { - Map values = (Map) msg.obj; - ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK); - callback.onReceiveValue((Long)values.get(USAGE)); - } break; - - case RETURN_QUOTA_ORIGIN: { - Map values = (Map) msg.obj; - ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK); - callback.onReceiveValue((Long)values.get(QUOTA)); - } break; - } - } - }; - } - } - - /** - * Message handler, WebCore side - * @hide - */ - public synchronized void createHandler() { - if (mHandler == null) { - mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case SET_QUOTA_ORIGIN: { - Origin website = (Origin) msg.obj; - nativeSetQuotaForOrigin(website.getOrigin(), - website.getQuota()); - } break; - - case DELETE_ORIGIN: { - Origin website = (Origin) msg.obj; - nativeDeleteOrigin(website.getOrigin()); - } break; - - case DELETE_ALL: - nativeDeleteAllData(); - break; - - case GET_ORIGINS: { - syncValues(); - ValueCallback callback = (ValueCallback) msg.obj; - Map origins = new HashMap(mOrigins); - Map values = new HashMap<String, Object>(); - values.put(CALLBACK, callback); - values.put(ORIGINS, origins); - postUIMessage(Message.obtain(null, RETURN_ORIGINS, values)); - } break; - - case GET_USAGE_ORIGIN: { - syncValues(); - Map values = (Map) msg.obj; - String origin = (String) values.get(ORIGIN); - ValueCallback callback = (ValueCallback) values.get(CALLBACK); - Origin website = mOrigins.get(origin); - Map retValues = new HashMap<String, Object>(); - retValues.put(CALLBACK, callback); - if (website != null) { - long usage = website.getUsage(); - retValues.put(USAGE, new Long(usage)); - } - postUIMessage(Message.obtain(null, RETURN_USAGE_ORIGIN, retValues)); - } break; - - case GET_QUOTA_ORIGIN: { - syncValues(); - Map values = (Map) msg.obj; - String origin = (String) values.get(ORIGIN); - ValueCallback callback = (ValueCallback) values.get(CALLBACK); - Origin website = mOrigins.get(origin); - Map retValues = new HashMap<String, Object>(); - retValues.put(CALLBACK, callback); - if (website != null) { - long quota = website.getQuota(); - retValues.put(QUOTA, new Long(quota)); - } - postUIMessage(Message.obtain(null, RETURN_QUOTA_ORIGIN, retValues)); - } break; - - case UPDATE: - syncValues(); - break; - } - } - }; - } - } - /* * When calling getOrigins(), getUsageForOrigin() and getQuotaForOrigin(), * we need to get the values from WebCore, but we cannot block while doing so @@ -270,26 +131,7 @@ public class WebStorage { * representation of the origin to a {@link WebStorage.Origin} object. */ public void getOrigins(ValueCallback<Map> callback) { - if (callback != null) { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - syncValues(); - callback.onReceiveValue(mOrigins); - } else { - postMessage(Message.obtain(null, GET_ORIGINS, callback)); - } - } - } - - /** - * Returns a list of origins having a database - * should only be called from WebViewCore. - */ - Collection<Origin> getOriginsSync() { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - update(); - return mOrigins.values(); - } - return null; + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -300,23 +142,7 @@ public class WebStorage { * a {@link ValueCallback}. */ public void getUsageForOrigin(String origin, ValueCallback<Long> callback) { - if (callback == null) { - return; - } - if (origin == null) { - callback.onReceiveValue(null); - return; - } - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - syncValues(); - Origin website = mOrigins.get(origin); - callback.onReceiveValue(new Long(website.getUsage())); - } else { - HashMap values = new HashMap<String, Object>(); - values.put(ORIGIN, origin); - values.put(CALLBACK, callback); - postMessage(Message.obtain(null, GET_USAGE_ORIGIN, values)); - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -327,23 +153,7 @@ public class WebStorage { * enforced on a per-origin basis for the Application Cache API. */ public void getQuotaForOrigin(String origin, ValueCallback<Long> callback) { - if (callback == null) { - return; - } - if (origin == null) { - callback.onReceiveValue(null); - return; - } - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - syncValues(); - Origin website = mOrigins.get(origin); - callback.onReceiveValue(new Long(website.getUsage())); - } else { - HashMap values = new HashMap<String, Object>(); - values.put(ORIGIN, origin); - values.put(CALLBACK, callback); - postMessage(Message.obtain(null, GET_QUOTA_ORIGIN, values)); - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -353,14 +163,7 @@ public class WebStorage { * for the Application Cache API. */ public void setQuotaForOrigin(String origin, long quota) { - if (origin != null) { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - nativeSetQuotaForOrigin(origin, quota); - } else { - postMessage(Message.obtain(null, SET_QUOTA_ORIGIN, - new Origin(origin, quota))); - } - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -369,14 +172,7 @@ public class WebStorage { * its string representation. */ public void deleteOrigin(String origin) { - if (origin != null) { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - nativeDeleteOrigin(origin); - } else { - postMessage(Message.obtain(null, DELETE_ORIGIN, - new Origin(origin))); - } - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -385,38 +181,7 @@ public class WebStorage { * Storage APIs. */ public void deleteAllData() { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - nativeDeleteAllData(); - } else { - postMessage(Message.obtain(null, DELETE_ALL)); - } - } - - /** - * Sets the maximum size of the ApplicationCache. - * This should only ever be called on the WebKit thread. - * @hide - */ - public void setAppCacheMaximumSize(long size) { - nativeSetAppCacheMaximumSize(size); - } - - /** - * Utility function to send a message to our handler - */ - private synchronized void postMessage(Message msg) { - if (mHandler != null) { - mHandler.sendMessage(msg); - } - } - - /** - * Utility function to send a message to the handler on the UI thread - */ - private void postUIMessage(Message msg) { - if (mUIHandler != null) { - mUIHandler.sendMessage(msg); - } + // Must be a no-op for backward compatibility: see the hidden constructor for reason. } /** @@ -424,37 +189,7 @@ public class WebStorage { * @return The singleton {@link WebStorage} instance. */ public static WebStorage getInstance() { - if (sWebStorage == null) { - sWebStorage = new WebStorage(); - } - return sWebStorage; - } - - /** - * @hide - * Post a Sync request - */ - public void update() { - if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - syncValues(); - } else { - postMessage(Message.obtain(null, UPDATE)); - } - } - - /** - * Run on the WebCore thread - * set the local values with the current ones - */ - private void syncValues() { - Set<String> tmp = nativeGetOrigins(); - mOrigins = new HashMap<String, Origin>(); - for (String origin : tmp) { - Origin website = new Origin(origin, - nativeGetQuotaForOrigin(origin), - nativeGetUsageForOrigin(origin)); - mOrigins.put(origin, website); - } + return WebViewFactory.getProvider().getWebStorage(); } /** @@ -466,13 +201,4 @@ public class WebStorage { * @hide */ public WebStorage() {} - - // Native functions - private static native Set nativeGetOrigins(); - private static native long nativeGetUsageForOrigin(String origin); - private static native long nativeGetQuotaForOrigin(String origin); - private static native void nativeSetQuotaForOrigin(String origin, long quota); - private static native void nativeDeleteOrigin(String origin); - private static native void nativeDeleteAllData(); - private static native void nativeSetAppCacheMaximumSize(long size); } diff --git a/core/java/android/webkit/WebStorageClassic.java b/core/java/android/webkit/WebStorageClassic.java new file mode 100644 index 0000000..62de5e6 --- /dev/null +++ b/core/java/android/webkit/WebStorageClassic.java @@ -0,0 +1,352 @@ +/* + * 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.os.Handler; +import android.os.Message; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** @hide */ +public class WebStorageClassic extends WebStorage { + // Global instance of a WebStorage + private static WebStorageClassic sWebStorage; + + // Message ids + static final int UPDATE = 0; + static final int SET_QUOTA_ORIGIN = 1; + static final int DELETE_ORIGIN = 2; + static final int DELETE_ALL = 3; + static final int GET_ORIGINS = 4; + static final int GET_USAGE_ORIGIN = 5; + static final int GET_QUOTA_ORIGIN = 6; + + // Message ids on the UI thread + static final int RETURN_ORIGINS = 0; + static final int RETURN_USAGE_ORIGIN = 1; + static final int RETURN_QUOTA_ORIGIN = 2; + + private static final String ORIGINS = "origins"; + private static final String ORIGIN = "origin"; + private static final String CALLBACK = "callback"; + private static final String USAGE = "usage"; + private static final String QUOTA = "quota"; + + private Map <String, Origin> mOrigins; + + private Handler mHandler = null; + private Handler mUIHandler = null; + + /** + * @hide + * Message handler, UI side + * @hide + */ + public void createUIHandler() { + if (mUIHandler == null) { + mUIHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case RETURN_ORIGINS: { + Map values = (Map) msg.obj; + Map origins = (Map) values.get(ORIGINS); + ValueCallback<Map> callback = (ValueCallback<Map>) values.get(CALLBACK); + callback.onReceiveValue(origins); + } break; + + case RETURN_USAGE_ORIGIN: { + Map values = (Map) msg.obj; + ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK); + callback.onReceiveValue((Long)values.get(USAGE)); + } break; + + case RETURN_QUOTA_ORIGIN: { + Map values = (Map) msg.obj; + ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK); + callback.onReceiveValue((Long)values.get(QUOTA)); + } break; + } + } + }; + } + } + + /** + * Message handler, WebCore side + * @hide + */ + public synchronized void createHandler() { + if (mHandler == null) { + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case SET_QUOTA_ORIGIN: { + Origin website = (Origin) msg.obj; + nativeSetQuotaForOrigin(website.getOrigin(), + website.getQuota()); + } break; + + case DELETE_ORIGIN: { + Origin website = (Origin) msg.obj; + nativeDeleteOrigin(website.getOrigin()); + } break; + + case DELETE_ALL: + nativeDeleteAllData(); + break; + + case GET_ORIGINS: { + syncValues(); + ValueCallback callback = (ValueCallback) msg.obj; + Map origins = new HashMap(mOrigins); + Map values = new HashMap<String, Object>(); + values.put(CALLBACK, callback); + values.put(ORIGINS, origins); + postUIMessage(Message.obtain(null, RETURN_ORIGINS, values)); + } break; + + case GET_USAGE_ORIGIN: { + syncValues(); + Map values = (Map) msg.obj; + String origin = (String) values.get(ORIGIN); + ValueCallback callback = (ValueCallback) values.get(CALLBACK); + Origin website = mOrigins.get(origin); + Map retValues = new HashMap<String, Object>(); + retValues.put(CALLBACK, callback); + if (website != null) { + long usage = website.getUsage(); + retValues.put(USAGE, new Long(usage)); + } + postUIMessage(Message.obtain(null, RETURN_USAGE_ORIGIN, retValues)); + } break; + + case GET_QUOTA_ORIGIN: { + syncValues(); + Map values = (Map) msg.obj; + String origin = (String) values.get(ORIGIN); + ValueCallback callback = (ValueCallback) values.get(CALLBACK); + Origin website = mOrigins.get(origin); + Map retValues = new HashMap<String, Object>(); + retValues.put(CALLBACK, callback); + if (website != null) { + long quota = website.getQuota(); + retValues.put(QUOTA, new Long(quota)); + } + postUIMessage(Message.obtain(null, RETURN_QUOTA_ORIGIN, retValues)); + } break; + + case UPDATE: + syncValues(); + break; + } + } + }; + } + } + + /* + * When calling getOrigins(), getUsageForOrigin() and getQuotaForOrigin(), + * we need to get the values from WebCore, but we cannot block while doing so + * as we used to do, as this could result in a full deadlock (other WebCore + * messages received while we are still blocked here, see http://b/2127737). + * + * We have to do everything asynchronously, by providing a callback function. + * We post a message on the WebCore thread (mHandler) that will get the result + * from WebCore, and we post it back on the UI thread (using mUIHandler). + * We can then use the callback function to return the value. + */ + + @Override + public void getOrigins(ValueCallback<Map> callback) { + if (callback != null) { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + syncValues(); + callback.onReceiveValue(mOrigins); + } else { + postMessage(Message.obtain(null, GET_ORIGINS, callback)); + } + } + } + + /** + * Returns a list of origins having a database + * should only be called from WebViewCore. + */ + Collection<Origin> getOriginsSync() { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + update(); + return mOrigins.values(); + } + return null; + } + + @Override + public void getUsageForOrigin(String origin, ValueCallback<Long> callback) { + if (callback == null) { + return; + } + if (origin == null) { + callback.onReceiveValue(null); + return; + } + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + syncValues(); + Origin website = mOrigins.get(origin); + callback.onReceiveValue(new Long(website.getUsage())); + } else { + HashMap values = new HashMap<String, Object>(); + values.put(ORIGIN, origin); + values.put(CALLBACK, callback); + postMessage(Message.obtain(null, GET_USAGE_ORIGIN, values)); + } + } + + @Override + public void getQuotaForOrigin(String origin, ValueCallback<Long> callback) { + if (callback == null) { + return; + } + if (origin == null) { + callback.onReceiveValue(null); + return; + } + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + syncValues(); + Origin website = mOrigins.get(origin); + callback.onReceiveValue(new Long(website.getUsage())); + } else { + HashMap values = new HashMap<String, Object>(); + values.put(ORIGIN, origin); + values.put(CALLBACK, callback); + postMessage(Message.obtain(null, GET_QUOTA_ORIGIN, values)); + } + } + + @Override + public void setQuotaForOrigin(String origin, long quota) { + if (origin != null) { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + nativeSetQuotaForOrigin(origin, quota); + } else { + postMessage(Message.obtain(null, SET_QUOTA_ORIGIN, + new Origin(origin, quota))); + } + } + } + + @Override + public void deleteOrigin(String origin) { + if (origin != null) { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + nativeDeleteOrigin(origin); + } else { + postMessage(Message.obtain(null, DELETE_ORIGIN, + new Origin(origin))); + } + } + } + + @Override + public void deleteAllData() { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + nativeDeleteAllData(); + } else { + postMessage(Message.obtain(null, DELETE_ALL)); + } + } + + /** + * Sets the maximum size of the ApplicationCache. + * This should only ever be called on the WebKit thread. + * Not part of the base-class API: this is only used by dump render tree. + */ + public void setAppCacheMaximumSize(long size) { + nativeSetAppCacheMaximumSize(size); + } + + /** + * Utility function to send a message to our handler + */ + private synchronized void postMessage(Message msg) { + if (mHandler != null) { + mHandler.sendMessage(msg); + } + } + + /** + * Utility function to send a message to the handler on the UI thread + */ + private void postUIMessage(Message msg) { + if (mUIHandler != null) { + mUIHandler.sendMessage(msg); + } + } + + /** + * Get the singleton instance of this class. + * @return The singleton {@link WebStorage} instance. + */ + public static WebStorageClassic getInstance() { + if (sWebStorage == null) { + sWebStorage = new WebStorageClassic(); + } + return sWebStorage; + } + + /** + * @hide + * Post a Sync request + */ + public void update() { + if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { + syncValues(); + } else { + postMessage(Message.obtain(null, UPDATE)); + } + } + + /** + * Run on the WebCore thread + * set the local values with the current ones + */ + private void syncValues() { + Set<String> tmp = nativeGetOrigins(); + mOrigins = new HashMap<String, Origin>(); + for (String origin : tmp) { + Origin website = new Origin(origin, + nativeGetQuotaForOrigin(origin), + nativeGetUsageForOrigin(origin)); + mOrigins.put(origin, website); + } + } + + WebStorageClassic() {} + + // Native functions + private static native Set nativeGetOrigins(); + private static native long nativeGetUsageForOrigin(String origin); + private static native long nativeGetQuotaForOrigin(String origin); + private static native void nativeSetQuotaForOrigin(String origin, long quota); + private static native void nativeDeleteOrigin(String origin); + private static native void nativeDeleteAllData(); + private static native void nativeSetAppCacheMaximumSize(long size); +} diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index bd10cca..f848430 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -268,12 +268,7 @@ public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener { - // Default Provider factory class name. - private static final String DEFAULT_WEB_VIEW_FACTORY = "android.webkit.WebViewClassic$Factory"; - private static final String LOGTAG = "webview_proxy"; - // TODO: flip DEBUG to always be disabled. - private static final boolean DEBUG = true; /** * Transportation object for returning WebView across thread boundaries. @@ -1702,16 +1697,11 @@ public class WebView extends AbsoluteLayout // Private internal stuff //------------------------------------------------------------------------- - // Cache the factory both for efficiency, and ensure any one process gets all webviews from the - // same provider. - private static WebViewFactoryProvider sProviderFactory; - private WebViewProvider mProvider; private void ensureProviderCreated() { checkThread(); if (mProvider == null) { - if (DEBUG) Log.v(LOGTAG, "instantiating webview provider instance"); // As this can get called during the base class constructor chain, pass the minimum // number of dependencies here; the rest are deferred to init(). mProvider = getFactory().createWebView(this, new PrivateAccess()); @@ -1722,30 +1712,7 @@ public class WebView extends AbsoluteLayout // For now the main purpose of this function (and the factory abstration) is to keep // us honest and minimize usage of WebViewClassic internals when binding the proxy. checkThread(); - if (sProviderFactory != null) return sProviderFactory; - - sProviderFactory = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY); - if (sProviderFactory == null) { - if (DEBUG) Log.v (LOGTAG, "Falling back to explicit linkage"); - sProviderFactory = new WebViewClassic.Factory(); - } - return sProviderFactory; - } - - private static WebViewFactoryProvider getFactoryByName(String providerName) { - try { - if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName); - Class<?> c = Class.forName(providerName); - if (DEBUG) Log.v(LOGTAG, "instantiating factory"); - return (WebViewFactoryProvider) c.newInstance(); - } catch (ClassNotFoundException e) { - Log.e(LOGTAG, "error loading " + providerName, e); - } catch (IllegalAccessException e) { - Log.e(LOGTAG, "error loading " + providerName, e); - } catch (InstantiationException e) { - Log.e(LOGTAG, "error loading " + providerName, e); - } - return null; + return WebViewFactory.getProvider(); } private static void checkThread() { diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 2793081..3bd9960 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -1459,14 +1459,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc static class Factory implements WebViewFactoryProvider, WebViewFactoryProvider.Statics { @Override - public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) { - return new WebViewClassic(webView, privateAccess); - } - - @Override - public Statics getStatics() { return this; } - - @Override public String findAddress(String addr) { return WebViewClassic.findAddress(addr); } @@ -1479,6 +1471,33 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } } + @Override + public Statics getStatics() { return this; } + + @Override + public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) { + return new WebViewClassic(webView, privateAccess); + } + + @Override + public GeolocationPermissions getGeolocationPermissions() { + return GeolocationPermissionsClassic.getInstance(); + } + + @Override + public CookieManager getCookieManager() { + return CookieManagerClassic.getInstance(); + } + + @Override + public WebIconDatabase getWebIconDatabase() { + return WebIconDatabaseClassic.getInstance(); + } + + @Override + public WebStorage getWebStorage() { + return WebStorageClassic.getInstance(); + } } private void onHandleUiEvent(MotionEvent event, int eventType, int flags) { diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 0565ed7..75141fd 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -189,10 +189,10 @@ public final class WebViewCore { // The WebIconDatabase needs to be initialized within the UI thread so // just request the instance here. WebIconDatabase.getInstance(); - // Create the WebStorage singleton and the UI handler - WebStorage.getInstance().createUIHandler(); + // Create the WebStorageClassic singleton and the UI handler + WebStorageClassic.getInstance().createUIHandler(); // Create the UI handler for GeolocationPermissions - GeolocationPermissions.getInstance().createUIHandler(); + GeolocationPermissionsClassic.getInstance().createUIHandler(); // Get the memory class of the current device. V8 will use these values // to GC more effectively. @@ -227,11 +227,11 @@ public final class WebViewCore { // Sync the native settings and also create the WebCore thread handler. mSettings.syncSettingsAndCreateHandler(mBrowserFrame); // Create the handler and transfer messages for the IconDatabase - WebIconDatabase.getInstance().createHandler(); - // Create the handler for WebStorage - WebStorage.getInstance().createHandler(); + WebIconDatabaseClassic.getInstance().createHandler(); + // Create the handler for WebStorageClassic + WebStorageClassic.getInstance().createHandler(); // Create the handler for GeolocationPermissions. - GeolocationPermissions.getInstance().createHandler(); + GeolocationPermissionsClassic.getInstance().createHandler(); // The transferMessages call will transfer all pending messages to the // WebCore thread handler. mEventHub.transferMessages(); @@ -1308,20 +1308,20 @@ public final class WebViewCore { break; case LOAD_URL: { - CookieManager.getInstance().waitForCookieOperationsToComplete(); + CookieManagerClassic.getInstance().waitForCookieOperationsToComplete(); GetUrlData param = (GetUrlData) msg.obj; loadUrl(param.mUrl, param.mExtraHeaders); break; } case POST_URL: { - CookieManager.getInstance().waitForCookieOperationsToComplete(); + CookieManagerClassic.getInstance().waitForCookieOperationsToComplete(); PostUrlData param = (PostUrlData) msg.obj; mBrowserFrame.postUrl(param.mUrl, param.mPostData); break; } case LOAD_DATA: - CookieManager.getInstance().waitForCookieOperationsToComplete(); + CookieManagerClassic.getInstance().waitForCookieOperationsToComplete(); BaseUrlData loadParams = (BaseUrlData) msg.obj; String baseUrl = loadParams.mBaseUrl; if (baseUrl != null) { @@ -2129,7 +2129,7 @@ public final class WebViewCore { // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize // callbacks. Computes the sum of database quota for all origins. private long getUsedQuota() { - WebStorage webStorage = WebStorage.getInstance(); + WebStorageClassic webStorage = WebStorageClassic.getInstance(); Collection<WebStorage.Origin> origins = webStorage.getOriginsSync(); if (origins == null) { diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java new file mode 100644 index 0000000..73ae910 --- /dev/null +++ b/core/java/android/webkit/WebViewFactory.java @@ -0,0 +1,64 @@ +/* + * 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.util.Log; + +/** + * Top level factory, used creating all the main WebView implementation classes. + */ +class WebViewFactory { + // Default Provider factory class name. + private static final String DEFAULT_WEB_VIEW_FACTORY = "android.webkit.WebViewClassic$Factory"; + + private static final String LOGTAG = "WebViewFactory"; + + private static final boolean DEBUG = false; + + // Cache the factory both for efficiency, and ensure any one process gets all webviews from the + // same provider. + private static WebViewFactoryProvider sProviderInstance; + + static synchronized WebViewFactoryProvider getProvider() { + // For now the main purpose of this function (and the factory abstraction) is to keep + // us honest and minimize usage of WebViewClassic internals when binding the proxy. + if (sProviderInstance != null) return sProviderInstance; + + sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY); + if (sProviderInstance == null) { + if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage"); + sProviderInstance = new WebViewClassic.Factory(); + } + return sProviderInstance; + } + + private static WebViewFactoryProvider getFactoryByName(String providerName) { + try { + if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName); + Class<?> c = Class.forName(providerName); + if (DEBUG) Log.v(LOGTAG, "instantiating factory"); + return (WebViewFactoryProvider) c.newInstance(); + } catch (ClassNotFoundException e) { + Log.e(LOGTAG, "error loading " + providerName, e); + } catch (IllegalAccessException e) { + Log.e(LOGTAG, "error loading " + providerName, e); + } catch (InstantiationException e) { + Log.e(LOGTAG, "error loading " + providerName, e); + } + return null; + } +} diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java index 22bf0bf..a832b0a 100644 --- a/core/java/android/webkit/WebViewFactoryProvider.java +++ b/core/java/android/webkit/WebViewFactoryProvider.java @@ -23,18 +23,6 @@ package android.webkit; * @hide */ public interface WebViewFactoryProvider { - - /** - * Construct a new WebView provider. - * @param webView the WebView instance bound to this implementation instance. Note it will not - * necessarily be fully constructed at the point of this call: defer real initialization to - * WebViewProvider.init(). - * @param privateAccess provides access into WebView internal methods. - */ - WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess); - - Statics getStatics(); - /** * This Interface provides glue for implementing the backend of WebView static methods which * cannot be implemented in-situ in the proxy class. @@ -53,4 +41,43 @@ public interface WebViewFactoryProvider { */ void setPlatformNotificationsEnabled(boolean enable); } + + Statics getStatics(); + + /** + * Construct a new WebViewProvider. + * @param webView the WebView instance bound to this implementation instance. Note it will not + * necessarily be fully constructed at the point of this call: defer real initialization to + * WebViewProvider.init(). + * @param privateAccess provides access into WebView internal methods. + */ + WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess); + + /** + * Gets the singleton GeolocationPermissions instance for this WebView implementation. The + * implementation must return the same instance on subsequent calls. + * @return the single GeolocationPermissions instance. + */ + GeolocationPermissions getGeolocationPermissions(); + + /** + * Gets the singleton CookieManager instance for this WebView implementation. The + * implementation must return the same instance on subsequent calls. + * @return the singleton CookieManager instance. + */ + CookieManager getCookieManager(); + + /** + * Gets the singleton WebIconDatabase instance for this WebView implementation. The + * implementation must return the same instance on subsequent calls. + * @return the singleton WebIconDatabase instance. + */ + WebIconDatabase getWebIconDatabase(); + + /** + * Gets the singleton WebStorage instance for this WebView implementation. The + * implementation must return the same instance on subsequent calls. + * @return the singleton WebStorage instance. + */ + WebStorage getWebStorage(); } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java index 740f544..d74f5f7 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java @@ -487,7 +487,7 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon } public void setAppCacheMaximumSize(long size) { - WebStorage.getInstance().setAppCacheMaximumSize(size); + android.webkit.WebStorageClassic.getInstance().setAppCacheMaximumSize(size); } public void setCanOpenWindows() { diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java index e608e2d..d0c59d3 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java @@ -66,7 +66,7 @@ public class LayoutTestController { public void setAppCacheMaximumSize(long size) { Log.i(LOG_TAG, "setAppCacheMaximumSize() called with: " + size); - WebStorage.getInstance().setAppCacheMaximumSize(size); + android.webkit.WebStorageClassic.getInstance().setAppCacheMaximumSize(size); } public void setCanOpenWindows() { |