SsoWebViewClient.java 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* ownCloud Android client application
  2. * Copyright (C) 2012-2013 ownCloud Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. package com.owncloud.android.authentication;
  18. import java.io.ByteArrayInputStream;
  19. import java.lang.ref.WeakReference;
  20. import java.security.cert.Certificate;
  21. import java.security.cert.CertificateException;
  22. import java.security.cert.CertificateFactory;
  23. import java.security.cert.X509Certificate;
  24. import com.owncloud.android.lib.common.network.NetworkUtils;
  25. import com.owncloud.android.lib.common.utils.Log_OC;
  26. import android.content.Context;
  27. import android.graphics.Bitmap;
  28. import android.net.http.SslCertificate;
  29. import android.net.http.SslError;
  30. import android.os.Bundle;
  31. import android.os.Handler;
  32. import android.os.Message;
  33. import android.view.KeyEvent;
  34. import android.view.View;
  35. import android.webkit.CookieManager;
  36. import android.webkit.HttpAuthHandler;
  37. import android.webkit.SslErrorHandler;
  38. import android.webkit.WebResourceResponse;
  39. import android.webkit.WebView;
  40. import android.webkit.WebViewClient;
  41. /**
  42. * Custom {@link WebViewClient} client aimed to catch the end of a single-sign-on process
  43. * running in the {@link WebView} that is attached to.
  44. *
  45. * Assumes that the single-sign-on is kept thanks to a cookie set at the end of the
  46. * authentication process.
  47. *
  48. * @author David A. Velasco
  49. */
  50. public class SsoWebViewClient extends WebViewClient {
  51. private static final String TAG = SsoWebViewClient.class.getSimpleName();
  52. public interface SsoWebViewClientListener {
  53. public void onSsoFinished(String sessionCookie);
  54. }
  55. private Context mContext;
  56. private Handler mListenerHandler;
  57. private WeakReference<SsoWebViewClientListener> mListenerRef;
  58. private String mTargetUrl;
  59. private String mLastReloadedUrlAtError;
  60. public SsoWebViewClient (Context context, Handler listenerHandler, SsoWebViewClientListener listener) {
  61. mContext = context;
  62. mListenerHandler = listenerHandler;
  63. mListenerRef = new WeakReference<SsoWebViewClient.SsoWebViewClientListener>(listener);
  64. mTargetUrl = "fake://url.to.be.set";
  65. mLastReloadedUrlAtError = null;
  66. }
  67. public String getTargetUrl() {
  68. return mTargetUrl;
  69. }
  70. public void setTargetUrl(String targetUrl) {
  71. mTargetUrl = targetUrl;
  72. }
  73. @Override
  74. public void onPageStarted (WebView view, String url, Bitmap favicon) {
  75. Log_OC.d(TAG, "onPageStarted : " + url);
  76. view.clearCache(true);
  77. super.onPageStarted(view, url, favicon);
  78. }
  79. @Override
  80. public void onFormResubmission (WebView view, Message dontResend, Message resend) {
  81. Log_OC.d(TAG, "onFormResubMission ");
  82. // necessary to grant reload of last page when device orientation is changed after sending a form
  83. resend.sendToTarget();
  84. }
  85. @Override
  86. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  87. return false;
  88. }
  89. @Override
  90. public void onReceivedError (WebView view, int errorCode, String description, String failingUrl) {
  91. Log_OC.e(TAG, "onReceivedError : " + failingUrl + ", code " + errorCode + ", description: " + description);
  92. if (!failingUrl.equals(mLastReloadedUrlAtError)) {
  93. view.reload();
  94. mLastReloadedUrlAtError = failingUrl;
  95. } else {
  96. mLastReloadedUrlAtError = null;
  97. super.onReceivedError(view, errorCode, description, failingUrl);
  98. }
  99. }
  100. @Override
  101. public void onPageFinished (WebView view, String url) {
  102. Log_OC.d(TAG, "onPageFinished : " + url);
  103. mLastReloadedUrlAtError = null;
  104. if (url.startsWith(mTargetUrl)) {
  105. view.setVisibility(View.GONE);
  106. CookieManager cookieManager = CookieManager.getInstance();
  107. final String cookies = cookieManager.getCookie(url);
  108. Log_OC.d(TAG, "Cookies: " + cookies);
  109. if (mListenerHandler != null && mListenerRef != null) {
  110. // this is good idea because onPageFinished is not running in the UI thread
  111. mListenerHandler.post(new Runnable() {
  112. @Override
  113. public void run() {
  114. SsoWebViewClientListener listener = mListenerRef.get();
  115. if (listener != null) {
  116. // Send Cookies to the listener
  117. listener.onSsoFinished(cookies);
  118. }
  119. }
  120. });
  121. }
  122. }
  123. }
  124. @Override
  125. public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) {
  126. Log_OC.d(TAG, "doUpdateVisitedHistory : " + url);
  127. }
  128. @Override
  129. public void onReceivedSslError (final WebView view, final SslErrorHandler handler, SslError error) {
  130. Log_OC.d(TAG, "onReceivedSslError : " + error);
  131. // Test 1
  132. X509Certificate x509Certificate = getX509CertificateFromError(error);
  133. boolean isKnownServer = false;
  134. if (x509Certificate != null) {
  135. Log_OC.d(TAG, "------>>>>> x509Certificate " + x509Certificate.toString());
  136. try {
  137. isKnownServer = NetworkUtils.isCertInKnownServersStore((Certificate) x509Certificate, mContext);
  138. } catch (Exception e) {
  139. Log_OC.e(TAG, "Exception: " + e.getMessage());
  140. }
  141. }
  142. if (isKnownServer) {
  143. handler.proceed();
  144. } else {
  145. ((AuthenticatorActivity)mContext).showUntrustedCertDialog(x509Certificate, error, handler);
  146. }
  147. }
  148. /**
  149. * Obtain the X509Certificate from SslError
  150. * @param error SslError
  151. * @return X509Certificate from error
  152. */
  153. public X509Certificate getX509CertificateFromError (SslError error) {
  154. Bundle bundle = SslCertificate.saveState(error.getCertificate());
  155. X509Certificate x509Certificate;
  156. byte[] bytes = bundle.getByteArray("x509-certificate");
  157. if (bytes == null) {
  158. x509Certificate = null;
  159. } else {
  160. try {
  161. CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
  162. Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
  163. x509Certificate = (X509Certificate) cert;
  164. } catch (CertificateException e) {
  165. x509Certificate = null;
  166. }
  167. }
  168. return x509Certificate;
  169. }
  170. @Override
  171. public void onReceivedHttpAuthRequest (WebView view, HttpAuthHandler handler, String host, String realm) {
  172. Log_OC.d(TAG, "onReceivedHttpAuthRequest : " + host);
  173. ((AuthenticatorActivity)mContext).createAuthenticationDialog(view, handler);
  174. }
  175. @Override
  176. public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
  177. Log_OC.d(TAG, "shouldInterceptRequest : " + url);
  178. return null;
  179. }
  180. @Override
  181. public void onLoadResource (WebView view, String url) {
  182. Log_OC.d(TAG, "onLoadResource : " + url);
  183. }
  184. @Override
  185. public void onReceivedLoginRequest (WebView view, String realm, String account, String args) {
  186. Log_OC.d(TAG, "onReceivedLoginRequest : " + realm + ", " + account + ", " + args);
  187. }
  188. @Override
  189. public void onScaleChanged (WebView view, float oldScale, float newScale) {
  190. Log_OC.d(TAG, "onScaleChanged : " + oldScale + " -> " + newScale);
  191. super.onScaleChanged(view, oldScale, newScale);
  192. }
  193. @Override
  194. public void onUnhandledKeyEvent (WebView view, KeyEvent event) {
  195. Log_OC.d(TAG, "onUnhandledKeyEvent : " + event);
  196. }
  197. @Override
  198. public boolean shouldOverrideKeyEvent (WebView view, KeyEvent event) {
  199. Log_OC.d(TAG, "shouldOverrideKeyEvent : " + event);
  200. return false;
  201. }
  202. }