/** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, * copy, modify, and distribute this software in source code or binary form for use * in connection with the web services and APIs provided by Facebook. * * As with any software that integrates with the Facebook platform, your use of * this software is subject to the Facebook Developer Principles and Policies * [http://developers.facebook.com/policy/]. This copyright notice shall be * included in all copies or substantial portions of the software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.facebook.internal; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import com.facebook.FacebookActivity; import com.facebook.FacebookException; import com.facebook.FacebookSdk; import com.facebook.appevents.AppEventsLogger; /** * com.facebook.internal is solely for the use of other packages within the * Facebook SDK for Android. Use of any of the classes in this package is * unsupported, and they may be modified or removed without warning at any time. */ public class DialogPresenter { public static void setupAppCallForCannotShowError(AppCall appCall) { FacebookException e = new FacebookException( "Unable to show the provided content. This typically means that the Facebook " + "app is not installed or up to date. If showing via the Web, this could " + "mean that the content has properties that are not supported via " + "this channel"); setupAppCallForValidationError(appCall, e); } public static void setupAppCallForValidationError( AppCall appCall, FacebookException validationError) { setupAppCallForErrorResult(appCall, validationError); } public interface ParameterProvider { Bundle getParameters(); Bundle getLegacyParameters(); } public static void present(AppCall appCall, Activity activity) { activity.startActivityForResult(appCall.getRequestIntent(), appCall.getRequestCode()); appCall.setPending(); } public static void present(AppCall appCall, Fragment fragment) { fragment.startActivityForResult(appCall.getRequestIntent(), appCall.getRequestCode()); appCall.setPending(); } public static boolean canPresentNativeDialogWithFeature( DialogFeature feature) { return getProtocolVersionForNativeDialog(feature) != NativeProtocol.NO_PROTOCOL_AVAILABLE; } public static boolean canPresentWebFallbackDialogWithFeature(DialogFeature feature) { return getDialogWebFallbackUri(feature) != null; } public static void setupAppCallForErrorResult(AppCall appCall, FacebookException exception) { if (exception == null) { return; } Intent errorResultIntent = new Intent(); errorResultIntent.setClass(FacebookSdk.getApplicationContext(), FacebookActivity.class); errorResultIntent.setAction(FacebookActivity.PASS_THROUGH_CANCEL_ACTION); NativeProtocol.setupProtocolRequestIntent( errorResultIntent, appCall.getCallId().toString(), null, NativeProtocol.getLatestKnownVersion(), NativeProtocol.createBundleForException(exception)); appCall.setRequestIntent(errorResultIntent); } public static void setupAppCallForWebDialog( AppCall appCall, String actionName, Bundle parameters) { Bundle intentParameters = new Bundle(); intentParameters.putString(NativeProtocol.WEB_DIALOG_ACTION, actionName); intentParameters.putBundle(NativeProtocol.WEB_DIALOG_PARAMS, parameters); Intent webDialogIntent = new Intent(); NativeProtocol.setupProtocolRequestIntent( webDialogIntent, appCall.getCallId().toString(), actionName, NativeProtocol.getLatestKnownVersion(), intentParameters); webDialogIntent.setClass(FacebookSdk.getApplicationContext(), FacebookActivity.class); webDialogIntent.setAction(FacebookDialogFragment.TAG); appCall.setRequestIntent(webDialogIntent); } public static void setupAppCallForWebFallbackDialog( AppCall appCall, Bundle parameters, DialogFeature feature) { String featureName = feature.name(); Uri fallbackUrl = getDialogWebFallbackUri(feature); if (fallbackUrl == null) { throw new FacebookException( "Unable to fetch the Url for the DialogFeature : '" + featureName + "'"); } // Since we're talking to the server here, let's use the latest version we know about. // We know we are going to be communicating over a bucketed protocol. int protocolVersion = NativeProtocol.getLatestKnownVersion(); Bundle webParams = ServerProtocol.getQueryParamsForPlatformActivityIntentWebFallback( appCall.getCallId().toString(), protocolVersion, parameters); if (webParams == null) { throw new FacebookException("Unable to fetch the app's key-hash"); } // Now form the Uri if (fallbackUrl.isRelative()) { fallbackUrl = Utility.buildUri( ServerProtocol.getDialogAuthority(), fallbackUrl.toString(), webParams); } else { fallbackUrl = Utility.buildUri( fallbackUrl.getAuthority(), fallbackUrl.getPath(), webParams); } Bundle intentParameters = new Bundle(); intentParameters.putString(NativeProtocol.WEB_DIALOG_URL, fallbackUrl.toString()); intentParameters.putBoolean(NativeProtocol.WEB_DIALOG_IS_FALLBACK, true); Intent webDialogIntent = new Intent(); NativeProtocol.setupProtocolRequestIntent( webDialogIntent, appCall.getCallId().toString(), feature.getAction(), NativeProtocol.getLatestKnownVersion(), intentParameters); webDialogIntent.setClass(FacebookSdk.getApplicationContext(), FacebookActivity.class); webDialogIntent.setAction(FacebookDialogFragment.TAG); appCall.setRequestIntent(webDialogIntent); } public static void setupAppCallForNativeDialog( AppCall appCall, ParameterProvider parameterProvider, DialogFeature feature) { Context context = FacebookSdk.getApplicationContext(); String action = feature.getAction(); int protocolVersion = getProtocolVersionForNativeDialog(feature); if (protocolVersion == NativeProtocol.NO_PROTOCOL_AVAILABLE) { throw new FacebookException( "Cannot present this dialog. This likely means that the " + "Facebook app is not installed."); } Bundle params; if (NativeProtocol.isVersionCompatibleWithBucketedIntent(protocolVersion)) { // Facebook app supports the new bucketed protocol params = parameterProvider.getParameters(); } else { // Facebook app only supports the old flat protocol params = parameterProvider.getLegacyParameters(); } if (params == null) { params = new Bundle(); } Intent intent = NativeProtocol.createPlatformActivityIntent( context, appCall.getCallId().toString(), action, protocolVersion, params); if (intent == null) { throw new FacebookException( "Unable to create Intent; this likely means the" + "Facebook app is not installed."); } appCall.setRequestIntent(intent); } private static Uri getDialogWebFallbackUri(DialogFeature feature) { String featureName = feature.name(); String action = feature.getAction(); String applicationId = FacebookSdk.getApplicationId(); Utility.DialogFeatureConfig config = Utility.getDialogFeatureConfig(applicationId, action, featureName); Uri fallbackUrl = null; if (config != null) { fallbackUrl = config.getFallbackUrl(); } return fallbackUrl; } public static int getProtocolVersionForNativeDialog( DialogFeature feature) { String applicationId = FacebookSdk.getApplicationId(); String action = feature.getAction(); int[] featureVersionSpec = getVersionSpecForFeature(applicationId, action, feature); return NativeProtocol.getLatestAvailableProtocolVersionForAction( action, featureVersionSpec); } private static int[] getVersionSpecForFeature( String applicationId, String actionName, DialogFeature feature) { // Return the value from DialogFeatureConfig if available. Otherwise, just // default to the min-version Utility.DialogFeatureConfig config = Utility.getDialogFeatureConfig(applicationId, actionName, feature.name()); if (config != null) { return config.getVersionSpec(); } else { return new int[]{feature.getMinVersion()}; } } public static void logDialogActivity( Context context, String eventName, String outcome) { AppEventsLogger logger = AppEventsLogger.newLogger(context); Bundle parameters = new Bundle(); parameters.putString(AnalyticsEvents.PARAMETER_DIALOG_OUTCOME, outcome); logger.logSdkEvent(eventName, null, parameters); } }