2

I am working an android app, which should run only on Android 4.2.2 device specifically.

The app has a Web View. In that Web View, I am loading a website, which is hosted on Firebase server.

  1. The website is secured with HTTPS
  2. The app uses WebViewClient to make SSL connections to the server.
  3. The connection to this site is encrypted and authenticated using TLS 1.2, ECDHE_RSA with X25519, and AES_128_GCM.


  1. I have added TLSScoketFactory for enabling TLS1.2. By default which is not enabled in 4.2.2 version.
  2. I am using okhttp client for request.
public class TLSSocketFactory extends SSLSocketFactory {

    private static final String TAG = "TLSSocketFactory";

    private SSLSocketFactory internalSSLSocketFactory;

    public TLSSocketFactory() {
        internalSSLSocketFactory = getSslContext().getSocketFactory();
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return internalSSLSocketFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return internalSSLSocketFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
    }

    private Socket enableTLSOnSocket(Socket socket) {
        if(socket != null && (socket instanceof SSLSocket)  && isTLSServerEnabled((SSLSocket) socket) ) {
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
        }
        return socket;
    }


    public static X509TrustManager getTrustManager() {
        return new X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
        };
    }

    public static SSLContext getSslContext() {
        try {
            SSLContext sslContext =  SSLContext.getInstance("TLS");
            sslContext.init(null, null, null);
            return sslContext;
        } catch (Exception ex) {
            Log.e(TAG, "Problem while getting SslContext", ex);
            throw new RuntimeException(ex);
        }
    }
}
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private static final String HTTP = "http://";
    private static final String HTTPS = "https://";
    private static final String CSS_FILE = ".css";
    private static final String JS_FILE = ".js";
    private static final String CSS_DIR = "/css/";
    private static final String JS_DIR = "/js/";

    private WebView webView;
    private ImageView button;
    private EditText urlView;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        progressBar.getProgressDrawable().setColorFilter(getResources().getColor(R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);

        urlView = (EditText) findViewById(R.id.url);

        webView = (WebView) findViewById(R.id.web_view);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        webView.setWebChromeClient(buildWebChromeClient());
        webView.setWebViewClient(buildClient());

        webView.post(new Runnable() {
            @Override
            public void run() {
                webView.loadUrl("https://sample-project.firebaseapp.com");
            }
        });

        button = (ImageView) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onButtonClick();
            }
        });
    }



    private WebViewClient buildClient() {
        return new WebViewClient() {

           private OkHttpClient okHttp = new OkHttpClient.Builder().sslSocketFactory(new TLSSocketFactory(), TLSSocketFactory.getTrustManager()).build();



            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                Log.e(TAG, "URL -> " + url);

             /*   if (url.contains(CSS_FILE) || url.contains(JS_FILE) || url.contains(CSS_DIR) || url.contains(JS_DIR)) {
                    Log.e(TAG, "Css or js -> default interceptor");
                    return super.shouldInterceptRequest(view, url);
                } else {*/
                    Request okHttpRequest = new Request.Builder().url(url).header("User-Agent", "OkHttp Example").build();
                    try {
                        Response response = okHttp.newCall(okHttpRequest).execute();
                        return new WebResourceResponse("text/html", "UTF-8", response.body().byteStream());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return null;
           //     }
            }

            public void onPageFinished(WebView view, String url) {
                Log.i(TAG, "Finished loading URL: " + url);
                super.onPageFinished(view, url);
             //   webView.loadUrl(url);
            }

            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
              //  MessageDialogFragment.getInstance(R.string.information, getString(R.string.oh_no) + description).show(getSupportFragmentManager(), "MessageDialogFragment");
                Log.i(TAG, "failing URL: " + failingUrl);
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed(); // Ignore SSL certificate errors
            }
        };
    }

    private WebChromeClient buildWebChromeClient() {
        return new WebChromeClient() {
            public void onProgressChanged(WebView view, int progress) {
                if (progress < 100 && progressBar.getVisibility() == ProgressBar.GONE) {
                    progressBar.setVisibility(ProgressBar.VISIBLE);
                }

                progressBar.setProgress(progress);
                if (progress == 100) {
                    progressBar.setVisibility(ProgressBar.GONE);
                }
            }

            @Override
            public boolean onConsoleMessage(ConsoleMessage m) {
                switch (m.messageLevel()) {
                    case LOG:
                        Log.i(TAG, String.format("%s (%s:%d)", m.message(), m.sourceId(), m.lineNumber()));
                        return true;
                    case TIP:
                        Log.v(TAG, String.format("%s (%s:%d)", m.message(), m.sourceId(), m.lineNumber()));
                        return true;
                    case DEBUG:
                        Log.d(TAG, String.format("%s (%s:%d)", m.message(), m.sourceId(), m.lineNumber()));
                        return true;
                    case WARNING:
                        Log.w(TAG, String.format("%s (%s:%d)", m.message(), m.sourceId(), m.lineNumber()));
                        return true;
                    case ERROR:
                        Log.e(TAG, String.format("%s (%s:%d)", m.message(), m.sourceId(), m.lineNumber()));
                        return true;
                }
                return false;
            }

        };
    }

    private void onButtonClick() {
        KeyboardManager.hideKeyboard(this, getCurrentFocus());

        if(NetworkManager.isNetworkEnable(this)) {
            String url = urlView.getText().toString();
            if (StringUtils.isNotBlank(url)) {
                if(!(url.startsWith(HTTP) || url.startsWith(HTTPS))){
               //     url = HTTP + url;
                }
              //  webView.loadUrl(url);
            } else {
                MessageDialogFragment.getInstance(R.string.information, getString(R.string.wrong_url)).show(getSupportFragmentManager(), "MessageDialogFragment");
            }
        } else {
            MessageDialogFragment.getInstance(R.string.information, getString(R.string.no_network)).show(getSupportFragmentManager(), "MessageDialogFragment");
        }
    }

}

The problem what I am facing when I try to load the website URL in WebView is

E/chromium: external/chromium/net/socket/ssl_client_socket_openssl.cc:792: [0102/102633:ERROR:ssl_client_socket_openssl.cc(792)] handshake failed; returned -1, SSL error code 1, net_error -107

Bulat
  • 720
  • 7
  • 15

0 Answers0