001package com.gigya.android.sdk.ui.provider;
002
003import android.annotation.SuppressLint;
004import android.content.DialogInterface;
005import android.graphics.Bitmap;
006import android.os.Build;
007import android.os.Bundle;
008import android.support.annotation.NonNull;
009import android.support.annotation.Nullable;
010import android.support.annotation.RequiresApi;
011import android.support.v4.app.FragmentTransaction;
012import android.support.v7.app.AppCompatActivity;
013import android.view.View;
014import android.webkit.JsResult;
015import android.webkit.WebChromeClient;
016import android.webkit.WebResourceError;
017import android.webkit.WebResourceRequest;
018import android.webkit.WebSettings;
019import android.webkit.WebView;
020import android.webkit.WebViewClient;
021
022import com.gigya.android.sdk.GigyaLogger;
023import com.gigya.android.sdk.ui.WebViewFragment;
024import com.gigya.android.sdk.utils.UrlUtils;
025
026import java.net.URLDecoder;
027import java.util.HashMap;
028import java.util.Map;
029
030public class ProviderFragment extends WebViewFragment {
031
032    private static final String LOG_TAG = "ProviderFragment";
033
034    /* Arguments. */
035    public static final String ARG_TITLE = "arg_title";
036    public static final String ARG_URL = "arg_url";
037    public static final String ARG_BODY = "arg_body";
038    public static final String ARG_REDIRECT_PREFIX = "arg_redirect_prefix";
039
040    @Nullable
041    private WebViewFragment.WebViewFragmentLifecycleCallbacks _resultCallback;
042
043    public static void present(AppCompatActivity activity, Bundle args, WebViewFragment.WebViewFragmentLifecycleCallbacks resultCallback) {
044        ProviderFragment fragment = new ProviderFragment();
045        fragment._resultCallback = resultCallback;
046        fragment.setArguments(args);
047        FragmentTransaction fragmentTransaction = activity.getSupportFragmentManager().beginTransaction();
048        fragmentTransaction.add(fragment, LOG_TAG);
049        fragmentTransaction.commitAllowingStateLoss();
050    }
051
052    @Override
053    public void onCreate(@Nullable Bundle savedInstanceState) {
054        super.onCreate(savedInstanceState);
055    }
056
057    @SuppressWarnings("unchecked")
058    @Override
059    protected void parseArguments() {
060        if (getArguments() == null) {
061            return;
062        }
063        Bundle args = getArguments();
064        _url = args.getString(ARG_URL);
065        _body = args.getString(ARG_BODY);
066        _redirectPrefix = args.getString(ARG_REDIRECT_PREFIX);
067        _title = args.getString(ARG_TITLE);
068        _params = (HashMap<String, Object>) args.getSerializable(ARG_PARAMS);
069    }
070
071    @SuppressWarnings("CharsetObjectCanBeUsed") // <- Only from API 19.
072    @Override
073    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
074        super.onViewCreated(view, savedInstanceState);
075        setUpWebView();
076        if (_url != null) {
077            if (_body != null) {
078                _webView.postUrl(_url, _body.getBytes());
079            } else {
080                // Load url.
081                _webView.loadUrl(_url);
082            }
083        }
084    }
085
086    @Override
087    public void onCancel(DialogInterface dialog) {
088        super.onCancel(dialog);
089        if (_resultCallback != null) {
090            _resultCallback.onWebViewCancel();
091        }
092        if (getActivity() != null) {
093            getActivity().onBackPressed();
094        }
095    }
096
097    @SuppressLint("SetJavaScriptEnabled")
098    @Override
099    protected void setUpWebView() {
100        super.setUpWebView();
101
102        /* Content UI & scrolling */
103        _webView.setVerticalScrollBarEnabled(true);
104        _webView.setHorizontalScrollBarEnabled(true);
105        _webView.setInitialScale(1);
106        _webView.setFocusable(true);
107
108        /* Web settings */
109        final WebSettings webSettings = _webView.getSettings();
110        webSettings.setSupportZoom(true);
111        webSettings.setBuiltInZoomControls(true);
112        webSettings.setUseWideViewPort(true);
113
114        _webView.setWebChromeClient(new WebChromeClient() {
115            @Override
116            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
117                result.confirm();
118                return true;
119            }
120        });
121        _webView.setWebViewClient(new WebViewClient() {
122
123            @Override
124            public void onPageStarted(WebView view, String url, Bitmap favicon) {
125                GigyaLogger.debug(LOG_TAG, "onPageStarted: with Url = " + url);
126                _progressBar.setVisibility(View.VISIBLE);
127            }
128
129            @Override
130            public void onPageFinished(WebView view, String url) {
131                GigyaLogger.debug(LOG_TAG, "onPageFinished: with Url = " + url);
132                _progressBar.setVisibility(View.INVISIBLE);
133            }
134
135            @Override
136            public boolean shouldOverrideUrlLoading(WebView view, String url) {
137                final String result = getOverrideResult(url);
138                if (result != null) {
139                    handleResult(UrlUtils.parseUrlParameters(result));
140                    return true;
141                }
142                return false;
143            }
144
145            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
146            @Override
147            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
148                final String result = getOverrideResult(request.getUrl().toString());
149                if (result != null) {
150                    handleResult(UrlUtils.parseUrlParameters(result));
151                    return true;
152                }
153                return false;
154            }
155
156            @Override
157            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
158                GigyaLogger.debug(LOG_TAG, error.toString());
159            }
160
161            @Nullable
162            private String getOverrideResult(String url) {
163                if (_redirectPrefix != null && _url != null) {
164                    if (url.startsWith(_redirectPrefix)) {
165                        try {
166                            final String decodedUrl = URLDecoder.decode(url, "UTF8");
167                            return decodedUrl.replace("gsapi", "http");
168                        } catch (Exception ex) {
169                            ex.printStackTrace();
170                        }
171                    }
172                }
173                return null;
174            }
175        });
176        _webView.setWebChromeClient(new WebChromeClient() {
177
178            @Override
179            public void onProgressChanged(WebView view, int newProgress) {
180                if (newProgress == 100 && _webView.getVisibility() == View.INVISIBLE) {
181                    // Actual loading finished.
182                    // Stub.
183                }
184            }
185        });
186    }
187
188    //region RESULT HANDLING
189
190    private void handleResult(@NonNull Map<String, Object> resultObject) {
191        GigyaLogger.debug(LOG_TAG, "handleResult: " + resultObject.toString());
192        if (getActivity() == null) {
193            // Irrelevant if activity instance is not available.
194            return;
195        }
196        if (_resultCallback != null) {
197            _resultCallback.onWebViewResult(resultObject);
198        }
199        // Remove fragment from stack. Do not finish host activity.
200        FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
201        fragmentTransaction.remove(this).commitAllowingStateLoss();
202
203        getActivity().finish();
204    }
205
206    //endregion
207}