summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Dixon <joth@google.com>2012-04-12 20:51:51 +0100
committerJonathan Dixon <joth@google.com>2012-04-23 12:43:02 +0100
commitd3101b1d300f5942fdb7dfa323dc8830c4edc007 (patch)
tree4140cbc09c362fd7584fec4f87dff13a79b22388
parenteb65757d24a97450fed160d66e86a4a62c392c5c (diff)
downloadframeworks_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
-rw-r--r--core/java/android/webkit/CookieManager.java140
-rw-r--r--core/java/android/webkit/CookieManagerClassic.java198
-rwxr-xr-xcore/java/android/webkit/GeolocationPermissions.java193
-rwxr-xr-xcore/java/android/webkit/GeolocationPermissionsClassic.java234
-rw-r--r--core/java/android/webkit/MustOverrideException.java25
-rw-r--r--core/java/android/webkit/WebIconDatabase.java229
-rw-r--r--core/java/android/webkit/WebIconDatabaseClassic.java289
-rw-r--r--core/java/android/webkit/WebSettings.java10
-rw-r--r--core/java/android/webkit/WebStorage.java300
-rw-r--r--core/java/android/webkit/WebStorageClassic.java352
-rw-r--r--core/java/android/webkit/WebView.java35
-rw-r--r--core/java/android/webkit/WebViewClassic.java35
-rw-r--r--core/java/android/webkit/WebViewCore.java22
-rw-r--r--core/java/android/webkit/WebViewFactory.java64
-rw-r--r--core/java/android/webkit/WebViewFactoryProvider.java51
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java2
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java2
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() {