001package com.gigya.android.sdk.ui;
002
003import android.app.Activity;
004import android.content.Context;
005import android.content.Intent;
006import android.net.Uri;
007import android.os.Bundle;
008import android.os.CountDownTimer;
009
010import com.gigya.android.sdk.GigyaLogger;
011import com.gigya.android.sdk.utils.UrlUtils;
012
013import java.util.HashMap;
014import java.util.Map;
015import java.util.concurrent.TimeUnit;
016
017
018public class WebLoginActivity extends Activity {
019
020    private static final String LOG_TAG = "WebLoginActivity";
021
022    private static final String EXTRA_LIFECYCLE_CALLBACK_ID = "web_login_lifecycle_callback";
023    private static final String EXTRA_URI = "web_login_uri";
024
025    private static final int REQUEST_CODE = 4040;
026
027    /*
028    Result handling and cancel dismissal timer.
029     */
030    private boolean _handledResult = false;
031    private CountDownTimer _cancelResultTimer;
032
033    public interface WebLoginActivityCallback {
034        void onResult(Activity activity, Map<String, Object> parsed);
035
036        void onCancelled();
037    }
038
039    private WebLoginActivityCallback _webLoginLifecycleCallbacks;
040    private int _webLoginLifecycleCallbacksId = -1;
041    private String _uri;
042
043    public static void present(Context context, String uri, WebLoginActivityCallback lifecycleCallback) {
044        Intent intent = new Intent(context, WebLoginActivity.class);
045        intent.putExtra(EXTRA_LIFECYCLE_CALLBACK_ID, Presenter.addWebLoginLifecycleCallback(lifecycleCallback));
046        intent.putExtra(EXTRA_URI, uri);
047        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
048        context.startActivity(intent);
049    }
050
051    @Override
052    protected void onCreate(Bundle savedInstanceState) {
053        super.onCreate(savedInstanceState);
054
055        if (getIntent() != null && getIntent().getExtras() != null) {
056            _webLoginLifecycleCallbacksId = getIntent().getIntExtra(EXTRA_LIFECYCLE_CALLBACK_ID, -1);
057            _uri = getIntent().getStringExtra(EXTRA_URI);
058            if (_webLoginLifecycleCallbacksId == -1) {
059                finish();
060                return;
061            }
062            if (_uri == null) {
063                finish();
064                return;
065            }
066            // Reference the callback using static getter from the Presenter. Same as the HostActivity.
067            _webLoginLifecycleCallbacks = Presenter.getWebLoginCallback(_webLoginLifecycleCallbacksId);
068        }
069
070        // Now that we have the callback.
071
072        final Uri uri = Uri.parse(_uri);
073        Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri);
074        browserIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
075        startActivityForResult(browserIntent, REQUEST_CODE);
076    }
077
078
079    @Override
080    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
081        if (requestCode == REQUEST_CODE) {
082            // Start short timer to see if result is being handled in the onNewIntent.
083            // Explanation: When using startActivityForResult with an ACTION_VIEW intent we will not receive the correct
084            // resultCode (Will always be 0 == Activity.RESULT_CANCELED). Therefore in order to determine when the user
085            // actually dismissed the browser we will use this short countdown timer as the onNewIntentCall should trigger
086            // immediately.
087            _cancelResultTimer = new CountDownTimer(TimeUnit.SECONDS.toMillis(1), TimeUnit.SECONDS.toMillis(1)) {
088
089                @Override
090                public void onTick(long millisUntilFinished) {
091                    GigyaLogger.debug(LOG_TAG, "Result countdown tick:");
092                }
093
094                @Override
095                public void onFinish() {
096                    if (!_handledResult && !isFinishing()) {
097                        _webLoginLifecycleCallbacks.onCancelled();
098                        finish();
099                    }
100                }
101            }.start();
102        } else {
103            super.onActivityResult(requestCode, resultCode, data);
104        }
105    }
106
107    @Override
108    protected void onNewIntent(Intent intent) {
109        super.onNewIntent(intent);
110
111
112        invalidateCancelTimer();
113
114        GigyaLogger.debug(LOG_TAG, "onNewIntent: " + intent.getAction());
115        final Uri data = intent.getData();
116        if (data == null) {
117            finish();
118            return;
119        }
120
121        // Reference identifiers to verify intent deep link.
122        final String packageName = getPackageName();
123        final String scheme = data.getScheme();
124        final String host = data.getHost();
125        final String pathPrefix = data.getPath();
126        if (scheme == null || host == null || pathPrefix == null) {
127            finish();
128            return;
129        }
130        // Evaluate intent-filter params,
131        if (scheme.equals("gigya") && host.equals("gsapi") && pathPrefix.equalsIgnoreCase("/" + packageName + "/login_result")) {
132
133            _handledResult = true;
134
135            final String encodedFragment = data.getEncodedFragment();
136            final Map<String, Object> parsed = new HashMap<>();
137            UrlUtils.parseUrlParameters(parsed, encodedFragment);
138            if (_webLoginLifecycleCallbacks != null && !isFinishing()) {
139                _webLoginLifecycleCallbacks.onResult(this, parsed);
140            }
141            finish();
142        } else {
143            finish();
144        }
145    }
146
147    private void invalidateCancelTimer() {
148        if (_cancelResultTimer != null) {
149            _cancelResultTimer.cancel();
150        }
151        _cancelResultTimer = null;
152    }
153
154    @Override
155    public void finish() {
156
157        _handledResult = false;
158
159        invalidateCancelTimer();
160
161        Presenter.flushWebLoginLifecycleCallback(_webLoginLifecycleCallbacksId);
162        super.finish();
163        /*
164        Disable exit animation.
165         */
166        overridePendingTransition(0, 0);
167    }
168}