Merge "Seperate interface and implementation of 4 WebView classes"
This commit is contained in:
committed by
Android (Google) Code Review
commit
47bc84760a
@@ -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);
|
||||
}
|
||||
|
||||
198
core/java/android/webkit/CookieManagerClassic.java
Normal file
198
core/java/android/webkit/CookieManagerClassic.java
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
234
core/java/android/webkit/GeolocationPermissionsClassic.java
Executable file
234
core/java/android/webkit/GeolocationPermissionsClassic.java
Executable file
@@ -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();
|
||||
}
|
||||
25
core/java/android/webkit/MustOverrideException.java
Normal file
25
core/java/android/webkit/MustOverrideException.java
Normal file
@@ -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!");
|
||||
}
|
||||
}
|
||||
@@ -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() {}
|
||||
}
|
||||
|
||||
289
core/java/android/webkit/WebIconDatabaseClassic.java
Normal file
289
core/java/android/webkit/WebIconDatabaseClassic.java
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
352
core/java/android/webkit/WebStorageClassic.java
Normal file
352
core/java/android/webkit/WebStorageClassic.java
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -1458,14 +1458,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
|
||||
// WebViewProvider bindings
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
64
core/java/android/webkit/WebViewFactory.java
Normal file
64
core/java/android/webkit/WebViewFactory.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user