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}