Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14792 manas 1
/**
2
 * Copyright 2010-present Facebook.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *    http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
package com.facebook.internal;
18
 
19
import android.content.Context;
20
import android.content.Intent;
21
import android.net.Uri;
22
import android.os.Bundle;
23
import android.os.Handler;
24
import android.os.Looper;
25
import android.webkit.WebView;
26
import com.facebook.FacebookException;
27
import com.facebook.widget.FacebookDialog;
28
import com.facebook.widget.WebDialog;
29
import org.json.JSONException;
30
import org.json.JSONObject;
31
 
32
/**
33
 * com.facebook.internal is solely for the use of other packages within the Facebook SDK for Android. Use of
34
 * any of the classes in this package is unsupported, and they may be modified or removed without warning at
35
 * any time.
36
 *
37
 * This dialog is used as a fallback when a native FacebookDialog could not be displayed. The primary reason for
38
 * this separation is to keep this approach for internal use only until we stabilize the API.
39
 */
40
public class FacebookWebFallbackDialog extends WebDialog {
41
    private static final String TAG = FacebookWebFallbackDialog.class.getName();
42
    private static final int OS_BACK_BUTTON_RESPONSE_TIMEOUT_MILLISECONDS = 1500;
43
 
44
    private boolean waitingForDialogToClose;
45
 
46
    public static boolean presentWebFallback(final Context context,
47
                                             String dialogUrl,
48
                                             String applicationId,
49
                                             final FacebookDialog.PendingCall appCall,
50
                                             final FacebookDialog.Callback callback) {
51
        if (Utility.isNullOrEmpty(dialogUrl)) {
52
            return false;
53
        }
54
 
55
        String redirectUrl = String.format("fb%s://bridge/", applicationId);
56
 
57
        // Show the webdialog.
58
        FacebookWebFallbackDialog fallbackWebDialog = new FacebookWebFallbackDialog(
59
                context, dialogUrl, redirectUrl);
60
        fallbackWebDialog.setOnCompleteListener(new WebDialog.OnCompleteListener() {
61
            @Override
62
            public void onComplete(Bundle values, FacebookException error) {
63
                Intent dummyIntent = new Intent();
64
                dummyIntent.putExtras(values == null ? new Bundle() : values);
65
                FacebookDialog.handleActivityResult(
66
                        context,
67
                        appCall,
68
                        appCall.getRequestCode(),
69
                        dummyIntent,
70
                        callback);
71
            }
72
        });
73
 
74
        fallbackWebDialog.show();
75
        return true;
76
    }
77
 
78
    private FacebookWebFallbackDialog(Context context, String url, String expectedRedirectUrl) {
79
        super(context, url);
80
 
81
        setExpectedRedirectUrl(expectedRedirectUrl);
82
    }
83
 
84
    @Override
85
    protected Bundle parseResponseUri(String url) {
86
        Uri responseUri = Uri.parse(url);
87
        Bundle queryParams = Utility.parseUrlQueryString(responseUri.getQuery());
88
 
89
        // Convert Bridge args to the format that the Native dialog code understands.
90
        String bridgeArgsJSONString = queryParams.getString(ServerProtocol.FALLBACK_DIALOG_PARAM_BRIDGE_ARGS);
91
        queryParams.remove(ServerProtocol.FALLBACK_DIALOG_PARAM_BRIDGE_ARGS);
92
 
93
        if (!Utility.isNullOrEmpty(bridgeArgsJSONString)) {
94
            Bundle bridgeArgs;
95
            try {
96
                JSONObject bridgeArgsJSON = new JSONObject(bridgeArgsJSONString);
97
                bridgeArgs = BundleJSONConverter.convertToBundle(bridgeArgsJSON);
98
                queryParams.putBundle(NativeProtocol.EXTRA_PROTOCOL_BRIDGE_ARGS, bridgeArgs);
99
            } catch (JSONException je) {
100
                Utility.logd(TAG, "Unable to parse bridge_args JSON", je);
101
            }
102
        }
103
 
104
        // Convert Method results to the format that the Native dialog code understands.
105
        String methodResultsJSONString = queryParams.getString(ServerProtocol.FALLBACK_DIALOG_PARAM_METHOD_RESULTS);
106
        queryParams.remove(ServerProtocol.FALLBACK_DIALOG_PARAM_METHOD_RESULTS);
107
 
108
        if (!Utility.isNullOrEmpty(methodResultsJSONString)) {
109
            methodResultsJSONString = Utility.isNullOrEmpty(methodResultsJSONString) ? "{}" : methodResultsJSONString;
110
            Bundle methodResults;
111
            try {
112
                JSONObject methodArgsJSON = new JSONObject(methodResultsJSONString);
113
                methodResults = BundleJSONConverter.convertToBundle(methodArgsJSON);
114
                queryParams.putBundle(NativeProtocol.EXTRA_PROTOCOL_METHOD_RESULTS, methodResults);
115
            } catch (JSONException je) {
116
                Utility.logd(TAG, "Unable to parse bridge_args JSON", je);
117
            }
118
        }
119
 
120
        // The web host does not send a numeric version back. Put the latest known version in there so NativeProtocol
121
        // can continue parsing the response.
122
        queryParams.remove(ServerProtocol.FALLBACK_DIALOG_PARAM_VERSION);
123
        queryParams.putInt(NativeProtocol.EXTRA_PROTOCOL_VERSION, NativeProtocol.getLatestKnownVersion());
124
 
125
        return queryParams;
126
    }
127
 
128
    @Override
129
    public void dismiss() {
130
        WebView webView = getWebView();
131
 
132
        if (isListenerCalled() || webView == null || !webView.isShown()) {
133
            // If the listener has been called, or if the WebView isn't visible, we cannot give the dialog a chance
134
            // to respond. So defer to the parent implementation.
135
            super.dismiss();
136
            return;
137
        }
138
 
139
        // If we have already notified the dialog to close, then ignore this request to dismiss. The timer will
140
        // honor the request.
141
        if (waitingForDialogToClose) {
142
            return;
143
        }
144
        waitingForDialogToClose = true;
145
 
146
        // Now fire off the event that will tell the dialog to wind down.
147
        String eventJS =
148
                "(function() {" +
149
                "  var event = document.createEvent('Event');" +
150
                "  event.initEvent('fbPlatformDialogMustClose',true,true);" +
151
                "  document.dispatchEvent(event);" +
152
                "})();";
153
        webView.loadUrl("javascript:" + eventJS);
154
 
155
        // Set up a timeout for the dialog to respond. If the timer expires, we need to honor the user's desire to
156
        // dismiss the dialog.
157
        Handler handler = new Handler(Looper.getMainLooper());
158
        handler.postDelayed(
159
                new Runnable() {
160
                    @Override
161
                    public void run() {
162
                        if (!isListenerCalled()) {
163
                            // If we get here, then the dialog did not close quickly enough. So we need to honor the user's
164
                            // wish to cancel.
165
                            sendCancelToListener();
166
                        }
167
                    }
168
                },
169
                OS_BACK_BUTTON_RESPONSE_TIMEOUT_MILLISECONDS);
170
    }
171
}