Fix synchronous xml requests with ssl errors.
Use the in-memory ssl preference table before posting a message to the WebCore thread. Since the WebCore thread is blocked waiting for the ssl resource, we cannot query the user for their preference. If the table does not contain the user's decision, bail on the request to avoid a deadlock. Also mark a few of the ssl handler's method's as synchronized. This was reported by findbugs.
This commit is contained in:
@@ -685,6 +685,17 @@ class LoadListener extends Handler implements EventHandler {
|
|||||||
" primary error: " + error.getPrimaryError() +
|
" primary error: " + error.getPrimaryError() +
|
||||||
" certificate: " + error.getCertificate());
|
" certificate: " + error.getCertificate());
|
||||||
}
|
}
|
||||||
|
// Check the cached preference table before sending a message. This
|
||||||
|
// will prevent waiting for an already available answer.
|
||||||
|
if (Network.getInstance(mContext).checkSslPrefTable(this, error)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Do not post a message for a synchronous request. This will cause a
|
||||||
|
// deadlock. Just bail on the request.
|
||||||
|
if (isSynchronous()) {
|
||||||
|
mRequestHandle.handleSslErrorResponse(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
sendMessageInternal(obtainMessage(MSG_SSL_ERROR, error));
|
sendMessageInternal(obtainMessage(MSG_SSL_ERROR, error));
|
||||||
// if it has been canceled, return false so that the network thread
|
// if it has been canceled, return false so that the network thread
|
||||||
// won't be blocked. If it is not canceled, save the mRequestHandle
|
// won't be blocked. If it is not canceled, save the mRequestHandle
|
||||||
|
|||||||
@@ -304,6 +304,14 @@ class Network {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ boolean checkSslPrefTable(LoadListener loader,
|
||||||
|
SslError error) {
|
||||||
|
if (loader != null && error != null) {
|
||||||
|
return mSslErrorHandler.checkSslPrefTable(loader, error);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles authentication requests on their way up to the user (the user
|
* Handles authentication requests on their way up to the user (the user
|
||||||
* must provide credentials).
|
* must provide credentials).
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ public class SslErrorHandler extends Handler {
|
|||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case HANDLE_RESPONSE:
|
case HANDLE_RESPONSE:
|
||||||
handleSslErrorResponse(msg.arg1 == 1);
|
LoadListener loader = (LoadListener) msg.obj;
|
||||||
|
handleSslErrorResponse(loader, loader.sslError(),
|
||||||
|
msg.arg1 == 1);
|
||||||
fastProcessQueuedSslErrors();
|
fastProcessQueuedSslErrors();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -76,7 +78,7 @@ public class SslErrorHandler extends Handler {
|
|||||||
* Saves this handler's state into a map.
|
* Saves this handler's state into a map.
|
||||||
* @return True iff succeeds.
|
* @return True iff succeeds.
|
||||||
*/
|
*/
|
||||||
/* package */ boolean saveState(Bundle outState) {
|
/* package */ synchronized boolean saveState(Bundle outState) {
|
||||||
boolean success = (outState != null);
|
boolean success = (outState != null);
|
||||||
if (success) {
|
if (success) {
|
||||||
// TODO?
|
// TODO?
|
||||||
@@ -90,7 +92,7 @@ public class SslErrorHandler extends Handler {
|
|||||||
* Restores this handler's state from a map.
|
* Restores this handler's state from a map.
|
||||||
* @return True iff succeeds.
|
* @return True iff succeeds.
|
||||||
*/
|
*/
|
||||||
/* package */ boolean restoreState(Bundle inState) {
|
/* package */ synchronized boolean restoreState(Bundle inState) {
|
||||||
boolean success = (inState != null);
|
boolean success = (inState != null);
|
||||||
if (success) {
|
if (success) {
|
||||||
success = inState.containsKey("ssl-error-handler");
|
success = inState.containsKey("ssl-error-handler");
|
||||||
@@ -126,6 +128,28 @@ public class SslErrorHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Processes queued SSL-error confirmation requests in
|
||||||
* a tight loop while there is no need to ask the user.
|
* a tight loop while there is no need to ask the user.
|
||||||
@@ -144,7 +168,9 @@ public class SslErrorHandler extends Handler {
|
|||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
// if this loader has been cancelled
|
// if this loader has been cancelled
|
||||||
if (loader.cancelled()) {
|
if (loader.cancelled()) {
|
||||||
// go to the following loader in the queue
|
// go to the following loader in the queue. Make sure this
|
||||||
|
// loader has been removed from the queue.
|
||||||
|
mLoaderQueue.remove(loader);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,18 +180,12 @@ public class SslErrorHandler extends Handler {
|
|||||||
Assert.assertNotNull(error);
|
Assert.assertNotNull(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int primary = error.getPrimaryError();
|
// checkSslPrefTable will handle the ssl error response if the
|
||||||
String host = loader.host();
|
// answer is available. It does not remove the loader from the
|
||||||
|
// queue.
|
||||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
if (checkSslPrefTable(loader, error)) {
|
||||||
Assert.assertTrue(host != null && primary != 0);
|
mLoaderQueue.remove(loader);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
if (mSslPrefTable.containsKey(host)) {
|
|
||||||
if (primary <= mSslPrefTable.getInt(host)) {
|
|
||||||
handleSslErrorResponse(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we do not have information on record, ask
|
// if we do not have information on record, ask
|
||||||
@@ -182,7 +202,7 @@ public class SslErrorHandler extends Handler {
|
|||||||
* Proceed with the SSL certificate.
|
* Proceed with the SSL certificate.
|
||||||
*/
|
*/
|
||||||
public void proceed() {
|
public void proceed() {
|
||||||
sendMessage(obtainMessage(HANDLE_RESPONSE, 1, 0));
|
sendMessage(obtainMessage(HANDLE_RESPONSE, 1, 0, mLoaderQueue.poll()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -190,16 +210,17 @@ public class SslErrorHandler extends Handler {
|
|||||||
* the error.
|
* the error.
|
||||||
*/
|
*/
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
sendMessage(obtainMessage(HANDLE_RESPONSE, 0, 0));
|
sendMessage(obtainMessage(HANDLE_RESPONSE, 0, 0, mLoaderQueue.poll()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles SSL error(s) on the way down from the user.
|
* Handles SSL error(s) on the way down from the user.
|
||||||
*/
|
*/
|
||||||
/* package */ synchronized void handleSslErrorResponse(boolean proceed) {
|
/* package */ synchronized void handleSslErrorResponse(LoadListener loader,
|
||||||
LoadListener loader = mLoaderQueue.poll();
|
SslError error, boolean proceed) {
|
||||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||||
Assert.assertNotNull(loader);
|
Assert.assertNotNull(loader);
|
||||||
|
Assert.assertNotNull(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||||
@@ -211,7 +232,7 @@ public class SslErrorHandler extends Handler {
|
|||||||
if (!loader.cancelled()) {
|
if (!loader.cancelled()) {
|
||||||
if (proceed) {
|
if (proceed) {
|
||||||
// update the user's SSL error preference table
|
// update the user's SSL error preference table
|
||||||
int primary = loader.sslError().getPrimaryError();
|
int primary = error.getPrimaryError();
|
||||||
String host = loader.host();
|
String host = loader.host();
|
||||||
|
|
||||||
if (DebugFlags.SSL_ERROR_HANDLER) {
|
if (DebugFlags.SSL_ERROR_HANDLER) {
|
||||||
|
|||||||
Reference in New Issue
Block a user