/** * 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.share.internal; import android.graphics.Bitmap; import android.net.Uri; import com.facebook.FacebookException; import com.facebook.FacebookSdk; import com.facebook.internal.Utility; import com.facebook.internal.Validate; import com.facebook.share.model.ShareContent; import com.facebook.share.model.ShareLinkContent; import com.facebook.share.model.ShareMedia; import com.facebook.share.model.ShareMediaContent; import com.facebook.share.model.ShareOpenGraphAction; import com.facebook.share.model.ShareOpenGraphContent; import com.facebook.share.model.ShareOpenGraphObject; import com.facebook.share.model.ShareOpenGraphValueContainer; import com.facebook.share.model.SharePhoto; import com.facebook.share.model.SharePhotoContent; import com.facebook.share.model.ShareVideo; import com.facebook.share.model.ShareVideoContent; import java.util.List; import java.util.Locale; import java.util.Set; /** * com.facebook.share.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 ShareContentValidation { private static Validator WebShareValidator; private static Validator DefaultValidator; private static Validator ApiValidator; public static void validateForMessage(ShareContent content) { validate(content, getDefaultValidator()); } public static void validateForNativeShare(ShareContent content) { validate(content, getDefaultValidator()); } public static void validateForWebShare(ShareContent content) { validate(content, getWebShareValidator()); } public static void validateForApiShare(ShareContent content) { validate(content, getApiValidator()); } private static Validator getDefaultValidator() { if (DefaultValidator == null) { DefaultValidator = new Validator(); } return DefaultValidator; } private static Validator getApiValidator() { if (ApiValidator == null) { ApiValidator = new ApiValidator(); } return ApiValidator; } private static Validator getWebShareValidator() { if (WebShareValidator == null) { WebShareValidator = new WebShareValidator(); } return WebShareValidator; } private static void validate(ShareContent content, Validator validator) throws FacebookException { if (content == null) { throw new FacebookException("Must provide non-null content to share"); } if (content instanceof ShareLinkContent) { validator.validate((ShareLinkContent) content); } else if (content instanceof SharePhotoContent) { validator.validate((SharePhotoContent) content); } else if (content instanceof ShareVideoContent) { validator.validate((ShareVideoContent) content); } else if (content instanceof ShareOpenGraphContent) { validator.validate((ShareOpenGraphContent) content); } else if (content instanceof ShareMediaContent) { validator.validate((ShareMediaContent) content); } } private static void validateLinkContent( ShareLinkContent linkContent, Validator validator) { Uri imageUrl = linkContent.getImageUrl(); if (imageUrl != null && !Utility.isWebUri(imageUrl)) { throw new FacebookException("Image Url must be an http:// or https:// url"); } } private static void validatePhotoContent( SharePhotoContent photoContent, Validator validator) { List<SharePhoto> photos = photoContent.getPhotos(); if (photos == null || photos.isEmpty()) { throw new FacebookException("Must specify at least one Photo in SharePhotoContent."); } if (photos.size() > ShareConstants.MAXIMUM_PHOTO_COUNT) { throw new FacebookException( String.format( Locale.ROOT, "Cannot add more than %d photos.", ShareConstants.MAXIMUM_PHOTO_COUNT)); } for (SharePhoto photo : photos) { validator.validate(photo); } } private static void validatePhoto(SharePhoto photo) { if (photo == null) { throw new FacebookException("Cannot share a null SharePhoto"); } Bitmap photoBitmap = photo.getBitmap(); Uri photoUri = photo.getImageUrl(); if (photoBitmap == null && photoUri == null) { throw new FacebookException("SharePhoto does not have a Bitmap or ImageUrl specified"); } } private static void validatePhotoForApi(SharePhoto photo, Validator validator) { validatePhoto(photo); Bitmap photoBitmap = photo.getBitmap(); Uri photoUri = photo.getImageUrl(); if (photoBitmap == null && Utility.isWebUri(photoUri) && !validator.isOpenGraphContent()) { throw new FacebookException( "Cannot set the ImageUrl of a SharePhoto to the Uri of an image on the " + "web when sharing SharePhotoContent"); } } private static void validatePhotoForNativeDialog(SharePhoto photo, Validator validator) { validatePhotoForApi(photo, validator); if (photo.getBitmap() != null || !Utility.isWebUri(photo.getImageUrl())) { Validate.hasContentProvider(FacebookSdk.getApplicationContext()); } } private static void validatePhotoForWebDialog(SharePhoto photo, Validator validator) { validatePhoto(photo); } private static void validateVideoContent( ShareVideoContent videoContent, Validator validator) { validator.validate(videoContent.getVideo()); SharePhoto previewPhoto = videoContent.getPreviewPhoto(); if (previewPhoto != null) { validator.validate(previewPhoto); } } private static void validateVideo(ShareVideo video, Validator validator) { if (video == null) { throw new FacebookException("Cannot share a null ShareVideo"); } Uri localUri = video.getLocalUrl(); if (localUri == null) { throw new FacebookException("ShareVideo does not have a LocalUrl specified"); } if (!Utility.isContentUri(localUri) && !Utility.isFileUri(localUri)) { throw new FacebookException("ShareVideo must reference a video that is on the device"); } } private static void validateMediaContent(ShareMediaContent mediaContent, Validator validator) { List<ShareMedia> media = mediaContent.getMedia(); if (media == null || media.isEmpty()) { throw new FacebookException("Must specify at least one medium in ShareMediaContent."); } if (media.size() > ShareConstants.MAXIMUM_MEDIA_COUNT) { throw new FacebookException( String.format( Locale.ROOT, "Cannot add more than %d media.", ShareConstants.MAXIMUM_MEDIA_COUNT)); } for (ShareMedia medium : media) { validator.validate(medium); } } public static void validateMedium(ShareMedia medium, Validator validator) { if (medium instanceof SharePhoto) { validator.validate((SharePhoto) medium); } else if (medium instanceof ShareVideo) { validator.validate((ShareVideo) medium); } else { throw new FacebookException( String.format( Locale.ROOT, "Invalid media type: %s", medium.getClass().getSimpleName())); } } private static void validateOpenGraphContent( ShareOpenGraphContent openGraphContent, Validator validator) { validator.validate(openGraphContent.getAction()); String previewPropertyName = openGraphContent.getPreviewPropertyName(); if (Utility.isNullOrEmpty(previewPropertyName)) { throw new FacebookException("Must specify a previewPropertyName."); } if (openGraphContent.getAction().get(previewPropertyName) == null) { throw new FacebookException( "Property \"" + previewPropertyName + "\" was not found on the action. " + "The name of the preview property must match the name of an " + "action property."); } } private static void validateOpenGraphAction( ShareOpenGraphAction openGraphAction, Validator validator) { if (openGraphAction == null) { throw new FacebookException("Must specify a non-null ShareOpenGraphAction"); } if (Utility.isNullOrEmpty(openGraphAction.getActionType())) { throw new FacebookException("ShareOpenGraphAction must have a non-empty actionType"); } validator.validate(openGraphAction, false); } private static void validateOpenGraphObject( ShareOpenGraphObject openGraphObject, Validator validator) { if (openGraphObject == null) { throw new FacebookException("Cannot share a null ShareOpenGraphObject"); } validator.validate(openGraphObject, true); } private static void validateOpenGraphValueContainer( ShareOpenGraphValueContainer valueContainer, Validator validator, boolean requireNamespace) { Set<String> keySet = valueContainer.keySet(); for (String key : keySet) { validateOpenGraphKey(key, requireNamespace); Object o = valueContainer.get(key); if (o instanceof List) { List list = (List) o; for (Object objectInList : list) { if (objectInList == null) { throw new FacebookException( "Cannot put null objects in Lists in " + "ShareOpenGraphObjects and ShareOpenGraphActions"); } validateOpenGraphValueContainerObject(objectInList, validator); } } else { validateOpenGraphValueContainerObject(o, validator); } } } private static void validateOpenGraphKey(String key, boolean requireNamespace) { if (!requireNamespace) { return; } String[] components = key.split(":"); if (components.length < 2) { throw new FacebookException("Open Graph keys must be namespaced: %s", key); } for (String component : components) { if (component.isEmpty()) { throw new FacebookException("Invalid key found in Open Graph dictionary: %s", key); } } } private static void validateOpenGraphValueContainerObject( Object o, Validator validator) { if (o instanceof ShareOpenGraphObject) { validator.validate((ShareOpenGraphObject) o); } else if (o instanceof SharePhoto) { validator.validate((SharePhoto) o); } } private static class WebShareValidator extends Validator { @Override public void validate(final ShareVideoContent videoContent) { throw new FacebookException("Cannot share ShareVideoContent via web sharing dialogs"); } @Override public void validate(ShareMediaContent mediaContent) { throw new FacebookException("Cannot share ShareMediaContent via web sharing dialogs"); } @Override public void validate(final SharePhoto photo) { validatePhotoForWebDialog(photo, this); } } private static class ApiValidator extends Validator { @Override public void validate(final SharePhoto photo) { validatePhotoForApi(photo, this); } @Override public void validate(ShareVideoContent videoContent) { if (!Utility.isNullOrEmpty(videoContent.getPlaceId())) { throw new FacebookException( "Cannot share video content with place IDs using the share api"); } if (!Utility.isNullOrEmpty(videoContent.getPeopleIds())) { throw new FacebookException( "Cannot share video content with people IDs using the share api"); } if (!Utility.isNullOrEmpty(videoContent.getRef())) { throw new FacebookException( "Cannot share video content with referrer URL using the share api"); } } @Override public void validate(ShareMediaContent mediaContent) { throw new FacebookException("Cannot share ShareMediaContent using the share api"); } @Override public void validate(ShareLinkContent linkContent) { if (!Utility.isNullOrEmpty(linkContent.getQuote())) { throw new FacebookException( "Cannot share link content with quote using the share api"); } } } private static class Validator { private boolean isOpenGraphContent = false; public void validate(final ShareLinkContent linkContent) { validateLinkContent(linkContent, this); } public void validate(final SharePhotoContent photoContent) { validatePhotoContent(photoContent, this); } public void validate(final ShareVideoContent videoContent) { validateVideoContent(videoContent, this); } public void validate(final ShareMediaContent mediaContent) { validateMediaContent(mediaContent, this); } public void validate(final ShareOpenGraphContent openGraphContent) { isOpenGraphContent = true; validateOpenGraphContent(openGraphContent, this); } public void validate(final ShareOpenGraphAction openGraphAction) { validateOpenGraphAction(openGraphAction, this); } public void validate(final ShareOpenGraphObject openGraphObject) { validateOpenGraphObject(openGraphObject, this); } public void validate(final ShareOpenGraphValueContainer openGraphValueContainer, boolean requireNamespace) { validateOpenGraphValueContainer(openGraphValueContainer, this, requireNamespace); } public void validate(final SharePhoto photo) { validatePhotoForNativeDialog(photo, this); } public void validate(final ShareVideo video) { validateVideo(video, this); } public void validate(final ShareMedia medium) { validateMedium(medium, this); } public boolean isOpenGraphContent() { return isOpenGraphContent; } } }