b/2864818 Prompt the SSL error dialog to user and proceed or cancel
the request. C++ side cl: https://android-git.corp.google.com/g/#change,84529 Change-Id: I1f4c69c6ddb92324a1ec3c193018e8d703454f56
This commit is contained in:
@@ -28,6 +28,8 @@ import android.net.Uri;
|
||||
import android.net.WebAddress;
|
||||
import android.net.http.ErrorStrings;
|
||||
import android.net.http.SslCertificate;
|
||||
import android.net.http.SslError;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.OpenableColumns;
|
||||
@@ -44,11 +46,15 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.harmony.security.provider.cert.X509CertImpl;
|
||||
|
||||
class BrowserFrame extends Handler {
|
||||
|
||||
private static final String LOGTAG = "webkit";
|
||||
@@ -1101,6 +1107,47 @@ class BrowserFrame extends Handler {
|
||||
mCallbackProxy.onReceivedHttpAuthRequest(handler, host, realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by JNI when the native HTTP(S) stack gets a invalid cert chain.
|
||||
*
|
||||
* We delegate the request to CallbackProxy, and route its response to
|
||||
* {@link #nativeSslCertErrorProceed(int)} or
|
||||
* {@link #nativeSslCertErrorCancel(int, int)}.
|
||||
*/
|
||||
private void reportSslCertError(final int handle, final int cert_error, byte cert_der[]) {
|
||||
final SslError ssl_error;
|
||||
try {
|
||||
X509Certificate cert = new X509CertImpl(cert_der);
|
||||
ssl_error = new SslError(cert_error, cert);
|
||||
} catch (IOException e) {
|
||||
// Can't get the cert, not much to do.
|
||||
Log.e(LOGTAG, "Can't get the certificate from WebKit, cancling");
|
||||
nativeSslCertErrorCancel(handle, cert_error);
|
||||
return;
|
||||
}
|
||||
|
||||
SslErrorHandler handler = new SslErrorHandler() {
|
||||
|
||||
@Override
|
||||
public void proceed() {
|
||||
SslCertLookupTable.getInstance().Allow(ssl_error);
|
||||
nativeSslCertErrorProceed(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
SslCertLookupTable.getInstance().Deny(ssl_error);
|
||||
nativeSslCertErrorCancel(handle, cert_error);
|
||||
}
|
||||
};
|
||||
|
||||
if (SslCertLookupTable.getInstance().IsAllowed(ssl_error)) {
|
||||
nativeSslCertErrorProceed(handle);
|
||||
} else {
|
||||
mCallbackProxy.onReceivedSslError(handler, ssl_error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by JNI when the native HTTP stack needs to download a file.
|
||||
*
|
||||
@@ -1246,4 +1293,7 @@ class BrowserFrame extends Handler {
|
||||
|
||||
private native void nativeAuthenticationProceed(int handle, String username, String password);
|
||||
private native void nativeAuthenticationCancel(int handle);
|
||||
|
||||
private native void nativeSslCertErrorProceed(int handle);
|
||||
private native void nativeSslCertErrorCancel(int handle, int cert_error);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ class Network {
|
||||
* SSL error handler: takes care of synchronization of multiple async
|
||||
* loaders with SSL-related problems.
|
||||
*/
|
||||
private SslErrorHandler mSslErrorHandler;
|
||||
private SslErrorHandlerImpl mSslErrorHandler;
|
||||
|
||||
/**
|
||||
* HTTP authentication handler: takes care of synchronization of HTTP
|
||||
@@ -157,7 +157,7 @@ class Network {
|
||||
getName().equals(WebViewCore.THREAD_NAME));
|
||||
}
|
||||
mContext = context;
|
||||
mSslErrorHandler = new SslErrorHandler();
|
||||
mSslErrorHandler = new SslErrorHandlerImpl();
|
||||
mHttpAuthHandler = new HttpAuthHandlerImpl(this);
|
||||
|
||||
mRequestQueue = new RequestQueue(context);
|
||||
|
||||
52
core/java/android/webkit/SslCertLookupTable.java
Normal file
52
core/java/android/webkit/SslCertLookupTable.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.Bundle;
|
||||
import android.net.http.SslError;
|
||||
|
||||
/*
|
||||
* A simple class to store the wrong certificates that user is aware but
|
||||
* chose to proceed.
|
||||
*/
|
||||
class SslCertLookupTable {
|
||||
private static SslCertLookupTable sTable;
|
||||
private final Bundle table;
|
||||
|
||||
public static synchronized SslCertLookupTable getInstance() {
|
||||
if (sTable == null) {
|
||||
sTable = new SslCertLookupTable();
|
||||
}
|
||||
return sTable;
|
||||
}
|
||||
|
||||
private SslCertLookupTable() {
|
||||
table = new Bundle();
|
||||
}
|
||||
|
||||
public void Allow(SslError ssl_error) {
|
||||
table.putBoolean(ssl_error.toString(), true);
|
||||
}
|
||||
|
||||
public void Deny(SslError ssl_error) {
|
||||
table.putBoolean(ssl_error.toString(), false);
|
||||
}
|
||||
|
||||
public boolean IsAllowed(SslError ssl_error) {
|
||||
return table.getBoolean(ssl_error.toString());
|
||||
}
|
||||
}
|
||||
@@ -16,258 +16,28 @@
|
||||
|
||||
package android.webkit;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import android.net.http.SslError;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* SslErrorHandler: class responsible for handling SSL errors. This class is
|
||||
* passed as a parameter to BrowserCallback.displaySslErrorDialog and is meant
|
||||
* to receive the user's response.
|
||||
* SslErrorHandler: class responsible for handling SSL errors.
|
||||
* This class is passed as a parameter to BrowserCallback.displaySslErrorDialog
|
||||
* and is meant to receive the user's response.
|
||||
*/
|
||||
public class SslErrorHandler extends Handler {
|
||||
/* One problem here is that there may potentially be multiple SSL errors
|
||||
* coming from mutiple loaders. Therefore, we keep a queue of loaders
|
||||
* that have SSL-related problems and process errors one by one in the
|
||||
* order they were received.
|
||||
*/
|
||||
|
||||
private static final String LOGTAG = "network";
|
||||
|
||||
/**
|
||||
* Queue of loaders that experience SSL-related problems.
|
||||
* Package-private constructor needed for API compatibility.
|
||||
*/
|
||||
private LinkedList<LoadListener> mLoaderQueue;
|
||||
|
||||
/**
|
||||
* SSL error preference table.
|
||||
*/
|
||||
private Bundle mSslPrefTable;
|
||||
|
||||
// These are only used in the client facing SslErrorHandler.
|
||||
private final SslErrorHandler mOriginHandler;
|
||||
private final LoadListener mLoadListener;
|
||||
|
||||
// Message id for handling the response
|
||||
private static final int HANDLE_RESPONSE = 100;
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case HANDLE_RESPONSE:
|
||||
LoadListener loader = (LoadListener) msg.obj;
|
||||
synchronized (SslErrorHandler.this) {
|
||||
handleSslErrorResponse(loader, loader.sslError(),
|
||||
msg.arg1 == 1);
|
||||
mLoaderQueue.remove(loader);
|
||||
fastProcessQueuedSslErrors();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new error handler with an empty loader queue.
|
||||
*/
|
||||
/* package */ SslErrorHandler() {
|
||||
mLoaderQueue = new LinkedList<LoadListener>();
|
||||
mSslPrefTable = new Bundle();
|
||||
|
||||
// These are used by client facing SslErrorHandlers.
|
||||
mOriginHandler = null;
|
||||
mLoadListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new error handler that will be passed to the client.
|
||||
*/
|
||||
private SslErrorHandler(SslErrorHandler origin, LoadListener listener) {
|
||||
mOriginHandler = origin;
|
||||
mLoadListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this handler's state into a map.
|
||||
* @return True iff succeeds.
|
||||
*/
|
||||
/* package */ synchronized boolean saveState(Bundle outState) {
|
||||
boolean success = (outState != null);
|
||||
if (success) {
|
||||
// TODO?
|
||||
outState.putBundle("ssl-error-handler", mSslPrefTable);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores this handler's state from a map.
|
||||
* @return True iff succeeds.
|
||||
*/
|
||||
/* package */ synchronized boolean restoreState(Bundle inState) {
|
||||
boolean success = (inState != null);
|
||||
if (success) {
|
||||
success = inState.containsKey("ssl-error-handler");
|
||||
if (success) {
|
||||
mSslPrefTable = inState.getBundle("ssl-error-handler");
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears SSL error preference table.
|
||||
*/
|
||||
/* package */ synchronized void clear() {
|
||||
mSslPrefTable.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles SSL error(s) on the way up to the user.
|
||||
*/
|
||||
/* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Log.v(LOGTAG, "SslErrorHandler.handleSslErrorRequest(): " +
|
||||
"url=" + loader.url());
|
||||
}
|
||||
|
||||
if (!loader.cancelled()) {
|
||||
mLoaderQueue.offer(loader);
|
||||
if (loader == mLoaderQueue.peek()) {
|
||||
fastProcessQueuedSslErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the preference table for a ssl error that has already been shown
|
||||
* to the user.
|
||||
*/
|
||||
/* package */ synchronized boolean checkSslPrefTable(LoadListener loader,
|
||||
SslError error) {
|
||||
final String host = loader.host();
|
||||
final int primary = error.getPrimaryError();
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertTrue(host != null && primary != 0);
|
||||
}
|
||||
|
||||
if (mSslPrefTable.containsKey(host)) {
|
||||
if (primary <= mSslPrefTable.getInt(host)) {
|
||||
handleSslErrorResponse(loader, error, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes queued SSL-error confirmation requests in
|
||||
* a tight loop while there is no need to ask the user.
|
||||
*/
|
||||
/* package */void fastProcessQueuedSslErrors() {
|
||||
while (processNextLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the next loader in the queue.
|
||||
* @return True iff should proceed to processing the
|
||||
* following loader in the queue
|
||||
*/
|
||||
private synchronized boolean processNextLoader() {
|
||||
LoadListener loader = mLoaderQueue.peek();
|
||||
if (loader != null) {
|
||||
// if this loader has been cancelled
|
||||
if (loader.cancelled()) {
|
||||
// go to the following loader in the queue. Make sure this
|
||||
// loader has been removed from the queue.
|
||||
mLoaderQueue.remove(loader);
|
||||
return true;
|
||||
}
|
||||
|
||||
SslError error = loader.sslError();
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertNotNull(error);
|
||||
}
|
||||
|
||||
// checkSslPrefTable will handle the ssl error response if the
|
||||
// answer is available. It does not remove the loader from the
|
||||
// queue.
|
||||
if (checkSslPrefTable(loader, error)) {
|
||||
mLoaderQueue.remove(loader);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if we do not have information on record, ask
|
||||
// the user (display a dialog)
|
||||
CallbackProxy proxy = loader.getFrame().getCallbackProxy();
|
||||
proxy.onReceivedSslError(new SslErrorHandler(this, loader), error);
|
||||
}
|
||||
|
||||
// the queue must be empty, stop
|
||||
return false;
|
||||
}
|
||||
SslErrorHandler() {}
|
||||
|
||||
/**
|
||||
* Proceed with the SSL certificate.
|
||||
*/
|
||||
public void proceed() {
|
||||
mOriginHandler.sendMessage(
|
||||
mOriginHandler.obtainMessage(
|
||||
HANDLE_RESPONSE, 1, 0, mLoadListener));
|
||||
}
|
||||
public void proceed() {}
|
||||
|
||||
/**
|
||||
* Cancel this request and all pending requests for the WebView that had
|
||||
* the error.
|
||||
*/
|
||||
public void cancel() {
|
||||
mOriginHandler.sendMessage(
|
||||
mOriginHandler.obtainMessage(
|
||||
HANDLE_RESPONSE, 0, 0, mLoadListener));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles SSL error(s) on the way down from the user.
|
||||
*/
|
||||
/* package */ synchronized void handleSslErrorResponse(LoadListener loader,
|
||||
SslError error, boolean proceed) {
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertNotNull(loader);
|
||||
Assert.assertNotNull(error);
|
||||
}
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Log.v(LOGTAG, "SslErrorHandler.handleSslErrorResponse():"
|
||||
+ " proceed: " + proceed
|
||||
+ " url:" + loader.url());
|
||||
}
|
||||
|
||||
if (!loader.cancelled()) {
|
||||
if (proceed) {
|
||||
// update the user's SSL error preference table
|
||||
int primary = error.getPrimaryError();
|
||||
String host = loader.host();
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertTrue(host != null && primary != 0);
|
||||
}
|
||||
boolean hasKey = mSslPrefTable.containsKey(host);
|
||||
if (!hasKey ||
|
||||
primary > mSslPrefTable.getInt(host)) {
|
||||
mSslPrefTable.putInt(host, primary);
|
||||
}
|
||||
}
|
||||
loader.handleSslErrorResponse(proceed);
|
||||
}
|
||||
}
|
||||
public void cancel() {}
|
||||
}
|
||||
|
||||
272
core/java/android/webkit/SslErrorHandlerImpl.java
Normal file
272
core/java/android/webkit/SslErrorHandlerImpl.java
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 junit.framework.Assert;
|
||||
|
||||
import android.net.http.SslError;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* SslErrorHandler's implementation for Android Java HTTP stack.
|
||||
* This class is not needed if the Chromium HTTP stack is used.
|
||||
*/
|
||||
class SslErrorHandlerImpl extends SslErrorHandler {
|
||||
/* One problem here is that there may potentially be multiple SSL errors
|
||||
* coming from multiple loaders. Therefore, we keep a queue of loaders
|
||||
* that have SSL-related problems and process errors one by one in the
|
||||
* order they were received.
|
||||
*/
|
||||
|
||||
private static final String LOGTAG = "network";
|
||||
|
||||
/**
|
||||
* Queue of loaders that experience SSL-related problems.
|
||||
*/
|
||||
private LinkedList<LoadListener> mLoaderQueue;
|
||||
|
||||
/**
|
||||
* SSL error preference table.
|
||||
*/
|
||||
private Bundle mSslPrefTable;
|
||||
|
||||
// These are only used in the client facing SslErrorHandler.
|
||||
private final SslErrorHandler mOriginHandler;
|
||||
private final LoadListener mLoadListener;
|
||||
|
||||
// Message id for handling the response
|
||||
private static final int HANDLE_RESPONSE = 100;
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case HANDLE_RESPONSE:
|
||||
LoadListener loader = (LoadListener) msg.obj;
|
||||
synchronized (SslErrorHandlerImpl.this) {
|
||||
handleSslErrorResponse(loader, loader.sslError(),
|
||||
msg.arg1 == 1);
|
||||
mLoaderQueue.remove(loader);
|
||||
fastProcessQueuedSslErrors();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new error handler with an empty loader queue.
|
||||
*/
|
||||
/* package */ SslErrorHandlerImpl() {
|
||||
mLoaderQueue = new LinkedList<LoadListener>();
|
||||
mSslPrefTable = new Bundle();
|
||||
|
||||
// These are used by client facing SslErrorHandlers.
|
||||
mOriginHandler = null;
|
||||
mLoadListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new error handler that will be passed to the client.
|
||||
*/
|
||||
private SslErrorHandlerImpl(SslErrorHandler origin, LoadListener listener) {
|
||||
mOriginHandler = origin;
|
||||
mLoadListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this handler's state into a map.
|
||||
* @return True iff succeeds.
|
||||
*/
|
||||
/* package */ synchronized boolean saveState(Bundle outState) {
|
||||
boolean success = (outState != null);
|
||||
if (success) {
|
||||
// TODO?
|
||||
outState.putBundle("ssl-error-handler", mSslPrefTable);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores this handler's state from a map.
|
||||
* @return True iff succeeds.
|
||||
*/
|
||||
/* package */ synchronized boolean restoreState(Bundle inState) {
|
||||
boolean success = (inState != null);
|
||||
if (success) {
|
||||
success = inState.containsKey("ssl-error-handler");
|
||||
if (success) {
|
||||
mSslPrefTable = inState.getBundle("ssl-error-handler");
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears SSL error preference table.
|
||||
*/
|
||||
/* package */ synchronized void clear() {
|
||||
mSslPrefTable.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles SSL error(s) on the way up to the user.
|
||||
*/
|
||||
/* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Log.v(LOGTAG, "SslErrorHandler.handleSslErrorRequest(): " +
|
||||
"url=" + loader.url());
|
||||
}
|
||||
|
||||
if (!loader.cancelled()) {
|
||||
mLoaderQueue.offer(loader);
|
||||
if (loader == mLoaderQueue.peek()) {
|
||||
fastProcessQueuedSslErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the preference table for a ssl error that has already been shown
|
||||
* to the user.
|
||||
*/
|
||||
/* package */ synchronized boolean checkSslPrefTable(LoadListener loader,
|
||||
SslError error) {
|
||||
final String host = loader.host();
|
||||
final int primary = error.getPrimaryError();
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertTrue(host != null && primary != 0);
|
||||
}
|
||||
|
||||
if (mSslPrefTable.containsKey(host)) {
|
||||
if (primary <= mSslPrefTable.getInt(host)) {
|
||||
handleSslErrorResponse(loader, error, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes queued SSL-error confirmation requests in
|
||||
* a tight loop while there is no need to ask the user.
|
||||
*/
|
||||
/* package */void fastProcessQueuedSslErrors() {
|
||||
while (processNextLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the next loader in the queue.
|
||||
* @return True iff should proceed to processing the
|
||||
* following loader in the queue
|
||||
*/
|
||||
private synchronized boolean processNextLoader() {
|
||||
LoadListener loader = mLoaderQueue.peek();
|
||||
if (loader != null) {
|
||||
// if this loader has been cancelled
|
||||
if (loader.cancelled()) {
|
||||
// go to the following loader in the queue. Make sure this
|
||||
// loader has been removed from the queue.
|
||||
mLoaderQueue.remove(loader);
|
||||
return true;
|
||||
}
|
||||
|
||||
SslError error = loader.sslError();
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertNotNull(error);
|
||||
}
|
||||
|
||||
// checkSslPrefTable will handle the ssl error response if the
|
||||
// answer is available. It does not remove the loader from the
|
||||
// queue.
|
||||
if (checkSslPrefTable(loader, error)) {
|
||||
mLoaderQueue.remove(loader);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if we do not have information on record, ask
|
||||
// the user (display a dialog)
|
||||
CallbackProxy proxy = loader.getFrame().getCallbackProxy();
|
||||
proxy.onReceivedSslError(new SslErrorHandlerImpl(this, loader), error);
|
||||
}
|
||||
|
||||
// the queue must be empty, stop
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proceed with the SSL certificate.
|
||||
*/
|
||||
public void proceed() {
|
||||
mOriginHandler.sendMessage(
|
||||
mOriginHandler.obtainMessage(
|
||||
HANDLE_RESPONSE, 1, 0, mLoadListener));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel this request and all pending requests for the WebView that had
|
||||
* the error.
|
||||
*/
|
||||
public void cancel() {
|
||||
mOriginHandler.sendMessage(
|
||||
mOriginHandler.obtainMessage(
|
||||
HANDLE_RESPONSE, 0, 0, mLoadListener));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles SSL error(s) on the way down from the user.
|
||||
*/
|
||||
/* package */ synchronized void handleSslErrorResponse(LoadListener loader,
|
||||
SslError error, boolean proceed) {
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertNotNull(loader);
|
||||
Assert.assertNotNull(error);
|
||||
}
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Log.v(LOGTAG, "SslErrorHandler.handleSslErrorResponse():"
|
||||
+ " proceed: " + proceed
|
||||
+ " url:" + loader.url());
|
||||
}
|
||||
|
||||
if (!loader.cancelled()) {
|
||||
if (proceed) {
|
||||
// update the user's SSL error preference table
|
||||
int primary = error.getPrimaryError();
|
||||
String host = loader.host();
|
||||
|
||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||
Assert.assertTrue(host != null && primary != 0);
|
||||
}
|
||||
boolean hasKey = mSslPrefTable.containsKey(host);
|
||||
if (!hasKey ||
|
||||
primary > mSslPrefTable.getInt(host)) {
|
||||
mSslPrefTable.putInt(host, primary);
|
||||
}
|
||||
}
|
||||
loader.handleSslErrorResponse(proceed);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user