/** * 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.login; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.text.TextUtils; import com.facebook.appevents.AppEventsLogger; import org.json.JSONException; import org.json.JSONObject; import java.util.Map; class LoginLogger { // Constants for logging login-related data. static final String EVENT_NAME_LOGIN_METHOD_START = "fb_mobile_login_method_start"; static final String EVENT_NAME_LOGIN_METHOD_COMPLETE = "fb_mobile_login_method_complete"; static final String EVENT_NAME_LOGIN_METHOD_NOT_TRIED = "fb_mobile_login_method_not_tried"; static final String EVENT_PARAM_METHOD_RESULT_SKIPPED = "skipped"; static final String EVENT_NAME_LOGIN_START = "fb_mobile_login_start"; static final String EVENT_NAME_LOGIN_COMPLETE = "fb_mobile_login_complete"; static final String EVENT_NAME_LOGIN_STATUS_START = "fb_mobile_login_status_start"; static final String EVENT_NAME_LOGIN_STATUS_COMPLETE = "fb_mobile_login_status_complete"; // Note: to ensure stability of column mappings across the four different event types, we // prepend a column index to each name, and we log all columns with all events, even if they are // empty. static final String EVENT_PARAM_AUTH_LOGGER_ID = "0_auth_logger_id"; static final String EVENT_PARAM_TIMESTAMP = "1_timestamp_ms"; static final String EVENT_PARAM_LOGIN_RESULT = "2_result"; static final String EVENT_PARAM_METHOD = "3_method"; static final String EVENT_PARAM_ERROR_CODE = "4_error_code"; static final String EVENT_PARAM_ERROR_MESSAGE = "5_error_message"; static final String EVENT_PARAM_EXTRAS = "6_extras"; static final String EVENT_PARAM_CHALLENGE = "7_challenge"; static final String EVENT_EXTRAS_TRY_LOGIN_ACTIVITY = "try_login_activity"; static final String EVENT_EXTRAS_MISSING_INTERNET_PERMISSION = "no_internet_permission"; static final String EVENT_EXTRAS_NOT_TRIED = "not_tried"; static final String EVENT_EXTRAS_NEW_PERMISSIONS = "new_permissions"; static final String EVENT_EXTRAS_LOGIN_BEHAVIOR = "login_behavior"; static final String EVENT_EXTRAS_REQUEST_CODE = "request_code"; static final String EVENT_EXTRAS_PERMISSIONS = "permissions"; static final String EVENT_EXTRAS_DEFAULT_AUDIENCE = "default_audience"; static final String EVENT_EXTRAS_IS_REAUTHORIZE = "isReauthorize"; static final String EVENT_EXTRAS_FACEBOOK_VERSION = "facebookVersion"; static final String EVENT_EXTRAS_FAILURE = "failure"; static final String FACEBOOK_PACKAGE_NAME = "com.facebook.katana"; private final AppEventsLogger appEventsLogger; private String applicationId; private String facebookVersion; LoginLogger(Context context, String applicationId) { this.applicationId = applicationId; appEventsLogger = AppEventsLogger.newLogger(context, applicationId); // Store which version of facebook is installed try { PackageManager packageManager = context.getPackageManager(); if (packageManager != null) { PackageInfo facebookInfo = packageManager.getPackageInfo(FACEBOOK_PACKAGE_NAME, 0); if (facebookInfo != null) { facebookVersion = facebookInfo.versionName; } } } catch (PackageManager.NameNotFoundException e) { // Do nothing, just ignore and not log } } public String getApplicationId() { return applicationId; } static Bundle newAuthorizationLoggingBundle(String authLoggerId) { // We want to log all parameters for all events, to ensure stability of columns across // different event types. Bundle bundle = new Bundle(); bundle.putLong(EVENT_PARAM_TIMESTAMP, System.currentTimeMillis()); bundle.putString(EVENT_PARAM_AUTH_LOGGER_ID, authLoggerId); bundle.putString(EVENT_PARAM_METHOD, ""); bundle.putString(EVENT_PARAM_LOGIN_RESULT, ""); bundle.putString(EVENT_PARAM_ERROR_MESSAGE, ""); bundle.putString(EVENT_PARAM_ERROR_CODE, ""); bundle.putString(EVENT_PARAM_EXTRAS, ""); return bundle; } public void logStartLogin(LoginClient.Request pendingLoginRequest) { Bundle bundle = newAuthorizationLoggingBundle(pendingLoginRequest.getAuthId()); // Log what we already know about the call in start event try { JSONObject extras = new JSONObject(); extras.put(EVENT_EXTRAS_LOGIN_BEHAVIOR, pendingLoginRequest.getLoginBehavior().toString()); extras.put(EVENT_EXTRAS_REQUEST_CODE, LoginClient.getLoginRequestCode()); extras.put(EVENT_EXTRAS_PERMISSIONS, TextUtils.join(",", pendingLoginRequest.getPermissions())); extras.put(EVENT_EXTRAS_DEFAULT_AUDIENCE, pendingLoginRequest.getDefaultAudience().toString()); extras.put(EVENT_EXTRAS_IS_REAUTHORIZE, pendingLoginRequest.isRerequest()); if (facebookVersion != null) { extras.put(EVENT_EXTRAS_FACEBOOK_VERSION, facebookVersion); } bundle.putString(EVENT_PARAM_EXTRAS, extras.toString()); } catch (JSONException e) { } appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_START, null, bundle); } public void logCompleteLogin(String loginRequestId, Map<String, String> loggingExtras, LoginClient.Result.Code result, Map<String, String> resultExtras, Exception exception) { Bundle bundle = newAuthorizationLoggingBundle(loginRequestId); if (result != null) { bundle.putString(EVENT_PARAM_LOGIN_RESULT, result.getLoggingValue()); } if (exception != null && exception.getMessage() != null) { bundle.putString(EVENT_PARAM_ERROR_MESSAGE, exception.getMessage()); } // Combine extras from the request and from the result. JSONObject jsonObject = null; if (!loggingExtras.isEmpty()) { jsonObject = new JSONObject(loggingExtras); } if (resultExtras != null) { if (jsonObject == null) { jsonObject = new JSONObject(); } try { for (Map.Entry<String, String> entry : resultExtras.entrySet()) { jsonObject.put(entry.getKey(), entry.getValue()); } } catch (JSONException e) { } } if (jsonObject != null) { bundle.putString(EVENT_PARAM_EXTRAS, jsonObject.toString()); } appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_COMPLETE, null, bundle); } public void logAuthorizationMethodStart(String authId, String method) { Bundle bundle = LoginLogger.newAuthorizationLoggingBundle(authId); bundle.putString(EVENT_PARAM_METHOD, method); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_METHOD_START, null, bundle); } public void logAuthorizationMethodComplete(String authId, String method, String result, String errorMessage, String errorCode, Map<String, String> loggingExtras) { Bundle bundle; bundle = LoginLogger.newAuthorizationLoggingBundle(authId); if (result != null) { bundle.putString(LoginLogger.EVENT_PARAM_LOGIN_RESULT, result); } if (errorMessage != null) { bundle.putString(LoginLogger.EVENT_PARAM_ERROR_MESSAGE, errorMessage); } if (errorCode != null) { bundle.putString(LoginLogger.EVENT_PARAM_ERROR_CODE, errorCode); } if (loggingExtras != null && !loggingExtras.isEmpty()) { JSONObject jsonObject = new JSONObject(loggingExtras); bundle.putString(LoginLogger.EVENT_PARAM_EXTRAS, jsonObject.toString()); } bundle.putString(EVENT_PARAM_METHOD, method); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_METHOD_COMPLETE, null, bundle); } public void logAuthorizationMethodNotTried(String authId, String method) { Bundle bundle = LoginLogger.newAuthorizationLoggingBundle(authId); bundle.putString(EVENT_PARAM_METHOD, method); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_METHOD_NOT_TRIED, null, bundle); } public void logLoginStatusStart(final String loggerRef) { Bundle bundle = LoginLogger.newAuthorizationLoggingBundle(loggerRef); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_STATUS_START, null, bundle); } public void logLoginStatusSuccess(final String loggerRef) { Bundle bundle = LoginLogger.newAuthorizationLoggingBundle(loggerRef); bundle.putString( EVENT_PARAM_LOGIN_RESULT, LoginClient.Result.Code.SUCCESS.getLoggingValue()); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_STATUS_COMPLETE, null, bundle); } public void logLoginStatusFailure(final String loggerRef) { Bundle bundle = LoginLogger.newAuthorizationLoggingBundle(loggerRef); bundle.putString(EVENT_PARAM_LOGIN_RESULT, EVENT_EXTRAS_FAILURE); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_STATUS_COMPLETE, null, bundle); } public void logLoginStatusError(final String loggerRef, final Exception exception) { Bundle bundle = LoginLogger.newAuthorizationLoggingBundle(loggerRef); bundle.putString( EVENT_PARAM_LOGIN_RESULT, LoginClient.Result.Code.ERROR.getLoggingValue()); bundle.putString(EVENT_PARAM_ERROR_MESSAGE, exception.toString()); appEventsLogger.logSdkEvent(EVENT_NAME_LOGIN_STATUS_COMPLETE, null, bundle); } public void logUnexpectedError(String eventName, String errorMessage) { logUnexpectedError(eventName, errorMessage, ""); } public void logUnexpectedError(String eventName, String errorMessage, String method) { Bundle bundle = newAuthorizationLoggingBundle(""); bundle.putString(EVENT_PARAM_LOGIN_RESULT, LoginClient.Result.Code.ERROR.getLoggingValue()); bundle.putString(EVENT_PARAM_ERROR_MESSAGE, errorMessage); bundle.putString(EVENT_PARAM_METHOD, method); appEventsLogger.logSdkEvent(eventName, null, bundle); } }