001package com.gigya.android.sdk.ui.plugin; 002 003import android.annotation.SuppressLint; 004import android.app.Dialog; 005import android.content.DialogInterface; 006import android.content.Intent; 007import android.content.pm.PackageManager; 008import android.graphics.Color; 009import android.graphics.drawable.ColorDrawable; 010import android.net.Uri; 011import android.os.Build; 012import android.os.Bundle; 013import android.support.annotation.NonNull; 014import android.support.annotation.Nullable; 015import android.support.v4.app.DialogFragment; 016import android.view.LayoutInflater; 017import android.view.View; 018import android.view.ViewGroup; 019import android.view.Window; 020import android.view.WindowManager; 021import android.webkit.WebSettings; 022import android.webkit.WebView; 023import android.widget.ProgressBar; 024 025import com.gigya.android.sdk.Config; 026import com.gigya.android.sdk.GigyaLogger; 027import com.gigya.android.sdk.GigyaPluginCallback; 028import com.gigya.android.sdk.R; 029import com.gigya.android.sdk.account.models.GigyaAccount; 030import com.gigya.android.sdk.ui.Presenter; 031 032@SuppressLint("ValidFragment") 033public class GigyaPluginFragment<A extends GigyaAccount> extends DialogFragment implements IGigyaPluginFragment<A> { 034 035 private static final String LOG_TAG = "GigyaPluginFragment"; 036 037 private static final String BASE_URL = "http://www.gigya.com"; 038 private static final String MIME_TYPE = "text/html"; 039 private static final String ENCODING = "utf-8"; 040 041 public static final String PLUGIN_SCREENSETS = "accounts.screenSet"; 042 public static final String PLUGIN_COMMENTS = "comments.commentsUI"; 043 044 /* 045 Web bridge invocation callback. Injected into the web bridge when initializing the fragment. 046 */ 047 public interface IBridgeCallbacks<A extends GigyaAccount> { 048 049 void invokeCallback(String invocation); 050 051 void onPluginEvent(GigyaPluginEvent event, String containerID); 052 053 void onPluginAuthEvent(@PluginAuthEventDef.PluginAuthEvent String method, @Nullable A accountObj); 054 } 055 056 // Dependencies. 057 private Config _config; 058 private IGigyaWebBridge<A> _gigyaWebBridge; 059 060 // Setter data. 061 private GigyaPluginCallback<A> _pluginCallback; 062 private String _html; 063 private boolean _obfuscation = false; 064 065 // Members. 066 private WebView _webView; 067 private ProgressBar _progressBar; 068 private GigyaPluginFileChooser _fileChooserClient; 069 070 public void setConfig(Config config) { 071 _config = config; 072 } 073 074 public void setWebBridge(IGigyaWebBridge<A> gigyaWebBridge) { 075 _gigyaWebBridge = gigyaWebBridge; 076 } 077 078 @Override 079 public void setCallback(GigyaPluginCallback<A> gigyaPluginCallback) { 080 _pluginCallback = gigyaPluginCallback; 081 } 082 083 @Override 084 public void setHtml(String html) { 085 _html = html; 086 } 087 088 //region LIFE CYCLE 089 090 @Override 091 public void onCreate(@Nullable Bundle savedInstanceState) { 092 super.onCreate(savedInstanceState); 093 094 // Parse arguments. 095 if (getArguments() != null) { 096 _obfuscation = getArguments().getBoolean(Presenter.ARG_OBFUSCATE, false); 097 } 098 } 099 100 101 @NonNull 102 @Override 103 public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { 104 Dialog dialog = super.onCreateDialog(savedInstanceState); 105 if (dialog.getWindow() != null) { 106 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 107 } 108 return dialog; 109 } 110 111 @Override 112 public void onStart() { 113 super.onStart(); 114 final Dialog dialog = getDialog(); 115 if (dialog != null) { 116 final Window window = dialog.getWindow(); 117 if (window != null) { 118 dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 119 final Bundle args = getArguments(); 120 if (args != null) { 121 // Check fullscreen mode request. 122 final boolean fullScreen = args.getBoolean(Presenter.ARG_STYLE_SHOW_FULL_SCREEN, false); 123 if (fullScreen) { 124 window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 125 } 126 } 127 } 128 } 129 } 130 131 @Override 132 public void onCancel(DialogInterface dialog) { 133 super.onCancel(dialog); 134 if (getActivity() != null) { 135 getActivity().onBackPressed(); 136 } 137 } 138 139 @Nullable 140 @Override 141 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 142 return inflater.inflate(R.layout.gigya_fragment_webview, container, false); 143 } 144 145 @Override 146 public void onDestroyView() { 147 if (_gigyaWebBridge != null) { 148 _gigyaWebBridge.detachFrom(_webView); 149 } 150 super.onDestroyView(); 151 } 152 153 @Override 154 public void onActivityResult(int requestCode, int resultCode, Intent data) { 155 evaluateActivityResult(requestCode, resultCode, data); 156 } 157 158 @Override 159 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 160 evaluatePermissionsResult(requestCode, permissions, grantResults); 161 } 162 163 @Override 164 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 165 setUpUiElements(view); 166 setUpWebViewElement(); 167 168 // Load URL. 169 loadUrl(view); 170 } 171 172 //endregion 173 174 @Override 175 public void setUpUiElements(final View fragmentView) { 176 // Reference UI elements. Must be called first! 177 _webView = fragmentView.findViewById(R.id.web_frag_web_view); 178 _progressBar = fragmentView.findViewById(R.id.web_frag_progress_bar); 179 } 180 181 @SuppressLint({"JavascriptInterface", "AddJavascriptInterface", "SetJavaScriptEnabled"}) 182 @Override 183 public void setUpWebViewElement() { 184 _fileChooserClient = new GigyaPluginFileChooser(this); 185 186 final WebSettings webSettings = _webView.getSettings(); 187 webSettings.setJavaScriptEnabled(true); 188 webSettings.setAllowFileAccess(true); 189 190 // Setting up a custom veb view client to handle WebView interaction. 191 _webView.setWebViewClient(_webViewClient); 192 _webView.setWebChromeClient(_fileChooserClient); 193 194 attachBridge(); 195 } 196 197 private void attachBridge() { 198 if (_pluginCallback == null) { 199 GigyaLogger.error(LOG_TAG, "Plugin callback is mandatory - cannot remain null."); 200 return; 201 } 202 // Web bridge. 203 _gigyaWebBridge.attachTo( 204 _webView, 205 new GigyaPluginCallback<A>() { 206 @Override 207 public void onError(GigyaPluginEvent event) { 208 _pluginCallback.onError(event); 209 } 210 211 @Override 212 public void onCanceled() { 213 _pluginCallback.onCanceled(); 214 } 215 216 @Override 217 public void onBeforeValidation(@NonNull GigyaPluginEvent event) { 218 _pluginCallback.onBeforeValidation(event); 219 } 220 221 @Override 222 public void onAfterValidation(@NonNull GigyaPluginEvent event) { 223 _pluginCallback.onAfterValidation(event); 224 } 225 226 @Override 227 public void onBeforeSubmit(@NonNull GigyaPluginEvent event) { 228 _pluginCallback.onBeforeSubmit(event); 229 } 230 231 @Override 232 public void onSubmit(@NonNull GigyaPluginEvent event) { 233 _pluginCallback.onSubmit(event); 234 } 235 236 @Override 237 public void onAfterSubmit(@NonNull GigyaPluginEvent event) { 238 _pluginCallback.onAfterSubmit(event); 239 } 240 241 @Override 242 public void onBeforeScreenLoad(@NonNull GigyaPluginEvent event) { 243 _pluginCallback.onBeforeScreenLoad(event); 244 } 245 246 @Override 247 public void onAfterScreenLoad(@NonNull GigyaPluginEvent event) { 248 _pluginCallback.onAfterScreenLoad(event); 249 } 250 251 @Override 252 public void onFieldChanged(@NonNull GigyaPluginEvent event) { 253 _pluginCallback.onFieldChanged(event); 254 } 255 256 @Override 257 public void onHide(@NonNull GigyaPluginEvent event, String reason) { 258 _pluginCallback.onHide(event, reason); 259 if (getActivity() != null) { 260 getActivity().onBackPressed(); 261 } 262 } 263 264 @Override 265 public void onLogin(@NonNull A accountObj) { 266 _pluginCallback.onLogin(accountObj); 267 } 268 269 @Override 270 public void onLogout() { 271 _pluginCallback.onLogout(); 272 } 273 274 @Override 275 public void onConnectionAdded() { 276 _pluginCallback.onConnectionAdded(); 277 } 278 279 @Override 280 public void onConnectionRemoved() { 281 _pluginCallback.onConnectionRemoved(); 282 } 283 }, 284 _progressBar); 285 } 286 287 @Override 288 public void loadUrl(final View fragmentView) { 289 fragmentView.post(new Runnable() { 290 @Override 291 public void run() { 292 _webView.loadDataWithBaseURL(BASE_URL, _html, MIME_TYPE, ENCODING, null); 293 } 294 }); 295 } 296 297 @Override 298 public void dismissWhenDone() { 299 300 } 301 302 @Override 303 public void evaluateActivityResult(int requestCode, int resultCode, Intent data) { 304 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 305 if (requestCode != GigyaPluginFileChooser.FILE_CHOOSER_MEDIA_REQUEST_CODE) { 306 super.onActivityResult(requestCode, resultCode, data); 307 } else { 308 _fileChooserClient.onActivityResult(resultCode, data); 309 } 310 } else { 311 super.onActivityResult(requestCode, resultCode, data); 312 } 313 } 314 315 @Override 316 public void evaluatePermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 317 if (requestCode == GigyaPluginFileChooser.FIRE_ACCESS_PERMISSION_REQUEST_CODE) { 318 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 319 GigyaLogger.debug(LOG_TAG, "External storage permission explicitly granted."); 320 _fileChooserClient.onRequestPermissionsResult(requestCode, permissions, grantResults); 321 } else { 322 // Permission denied by the user. 323 GigyaLogger.debug(LOG_TAG, "External storage permission explicitly denied."); 324 } 325 } 326 } 327 328 /* 329 Web View client implementations. 330 */ 331 private GigyaPluginWebViewClient _webViewClient = new GigyaPluginWebViewClient( 332 new IGigyaPluginWebViewClientInteractions() { 333 334 @Override 335 public void onPageStarted() { 336 _progressBar.setVisibility(View.VISIBLE); 337 } 338 339 @Override 340 public void onPageError(GigyaPluginEvent errorEvent) { 341 _pluginCallback.onError(errorEvent); 342 } 343 344 @Override 345 public boolean onUrlInvoke(String url) { 346 return _gigyaWebBridge.invoke(url); 347 } 348 349 @Override 350 public void onBrowserIntent(Uri uri) { 351 Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri); 352 startActivity(browserIntent); 353 } 354 }); 355}