From 578c367f5b1d13af2d15501cab244aef14a75d3c Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Wed, 16 Jul 2014 12:57:47 +0200 Subject: [PATCH] added http proxy authentication (see #819) --- mobile/res/layout/http_authentication.xml | 62 +++++++ mobile/res/values/strings.xml | 17 ++ .../iitc_mobile/HttpAuthenticationDialog.java | 166 ++++++++++++++++++ .../com/cradle/iitc_mobile/IITC_Mobile.java | 1 + .../iitc_mobile/IITC_WebViewClient.java | 40 +++++ 5 files changed, 286 insertions(+) create mode 100644 mobile/res/layout/http_authentication.xml create mode 100644 mobile/src/com/cradle/iitc_mobile/HttpAuthenticationDialog.java diff --git a/mobile/res/layout/http_authentication.xml b/mobile/res/layout/http_authentication.xml new file mode 100644 index 00000000..7309f27c --- /dev/null +++ b/mobile/res/layout/http_authentication.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml index ed36fa12..56802e6c 100644 --- a/mobile/res/values/strings.xml +++ b/mobile/res/values/strings.xml @@ -219,6 +219,23 @@ Copied to clipboard… Do not show again + + Sign in to %1$s %2$s" + + Name + + Password + + Sign in + + Save bookmark + + Browser + + Cancel + + OK + Locate Share Intel diff --git a/mobile/src/com/cradle/iitc_mobile/HttpAuthenticationDialog.java b/mobile/src/com/cradle/iitc_mobile/HttpAuthenticationDialog.java new file mode 100644 index 00000000..1b92aac5 --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/HttpAuthenticationDialog.java @@ -0,0 +1,166 @@ +/* +* 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 com.cradle.iitc_mobile; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; + +/** +* HTTP authentication dialog. +*/ +public class HttpAuthenticationDialog { + + private final Context mContext; + + private final String mHost; + private final String mRealm; + + private AlertDialog mDialog; + private TextView mUsernameView; + private TextView mPasswordView; + + private OkListener mOkListener; + private CancelListener mCancelListener; + + /** +* Creates an HTTP authentication dialog. +*/ + public HttpAuthenticationDialog(Context context, String host, String realm) { + mContext = context; + mHost = host; + mRealm = realm; + createDialog(); + } + + private String getUsername() { + return mUsernameView.getText().toString(); + } + + private String getPassword() { + return mPasswordView.getText().toString(); + } + + /** +* Sets the listener that will be notified when the user submits the credentials. +*/ + public void setOkListener(OkListener okListener) { + mOkListener = okListener; + } + + /** +* Sets the listener that will be notified when the user cancels the authentication +* dialog. +*/ + public void setCancelListener(CancelListener cancelListener) { + mCancelListener = cancelListener; + } + + /** +* Shows the dialog. +*/ + public void show() { + mDialog.show(); + mUsernameView.requestFocus(); + } + + /** +* Hides, recreates, and shows the dialog. This can be used to handle configuration changes. +*/ + public void reshow() { + String username = getUsername(); + String password = getPassword(); + int focusId = mDialog.getCurrentFocus().getId(); + mDialog.dismiss(); + createDialog(); + mDialog.show(); + if (username != null) { + mUsernameView.setText(username); + } + if (password != null) { + mPasswordView.setText(password); + } + if (focusId != 0) { + mDialog.findViewById(focusId).requestFocus(); + } else { + mUsernameView.requestFocus(); + } + } + + private void createDialog() { + LayoutInflater factory = LayoutInflater.from(mContext); + View v = factory.inflate(R.layout.http_authentication, null); + mUsernameView = (TextView) v.findViewById(R.id.username_edit); + mPasswordView = (TextView) v.findViewById(R.id.password_edit); + mPasswordView.setOnEditorActionListener(new OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + mDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); + return true; + } + return false; + } + }); + + String title = mContext.getText(R.string.sign_in_to).toString(); + title = String.format(title, mHost, mRealm); + + mDialog = new AlertDialog.Builder(mContext) + .setTitle(title) + .setIconAttribute(android.R.attr.alertDialogIcon) + .setView(v) + .setPositiveButton(R.string.action, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + if (mOkListener != null) { + mOkListener.onOk(mHost, mRealm, getUsername(), getPassword()); + } + }}) + .setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + if (mCancelListener != null) mCancelListener.onCancel(); + }}) + .setOnCancelListener(new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + if (mCancelListener != null) mCancelListener.onCancel(); + }}) + .create(); + + // Make the IME appear when the dialog is displayed if applicable. + mDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + } + + /** +* Interface for listeners that are notified when the user submits the credentials. +*/ + public interface OkListener { + void onOk(String host, String realm, String username, String password); + } + + /** +* Interface for listeners that are notified when the user cancels the dialog. +*/ + public interface CancelListener { + void onCancel(); + } +} diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index 4b54fe96..b713de95 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -31,6 +31,7 @@ import android.view.Window; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.webkit.CookieManager; +import android.webkit.HttpAuthHandler; import android.webkit.WebView; import android.widget.EditText; import android.widget.ImageButton; diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index 84886807..c5b036a9 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -1,5 +1,6 @@ package com.cradle.iitc_mobile; +import android.app.ActionBar; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -7,6 +8,7 @@ import android.net.http.SslError; import android.os.Environment; import android.preference.PreferenceManager; import android.text.TextUtils; +import android.webkit.HttpAuthHandler; import android.webkit.SslErrorHandler; import android.webkit.WebResourceResponse; import android.webkit.WebView; @@ -168,6 +170,44 @@ public class IITC_WebViewClient extends WebViewClient { } } + @Override + public void onReceivedHttpAuthRequest(WebView view, final HttpAuthHandler handler, + final String host, final String realm) { + String username = null; + String password = null; + + boolean reuseHttpAuthUsernamePassword + = handler.useHttpAuthUsernamePassword(); + + if (reuseHttpAuthUsernamePassword && view != null) { + String[] credentials = view.getHttpAuthUsernamePassword(host, realm); + if (credentials != null && credentials.length == 2) { + username = credentials[0]; + password = credentials[1]; + } + } + + if (username != null && password != null) { + handler.proceed(username, password); + } else { + HttpAuthenticationDialog dialog = new HttpAuthenticationDialog(mIitc, host, realm); + + dialog.setOkListener(new HttpAuthenticationDialog.OkListener() { + public void onOk(String host, String realm, String username, String password) { + handler.proceed(username, password); + } + }); + + dialog.setCancelListener(new HttpAuthenticationDialog.CancelListener() { + public void onCancel() { + handler.cancel(); + } + }); + + dialog.show(); + } + } + public void reset() { mIitcInjected = false; }