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}