/**
* 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.internal.Utility;
import com.facebook.share.model.ShareContent;
import com.facebook.share.model.ShareLinkContent;
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;
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, getDefaultValidator());
}
private static Validator getDefaultValidator() {
if (DefaultValidator == null) {
DefaultValidator = new Validator();
}
return DefaultValidator;
}
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);
}
}
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 validatePhotoForNativeDialog(SharePhoto photo, Validator validator) {
if (photo == null) {
throw new FacebookException("Cannot share a null SharePhoto");
}
Bitmap photoBitmap = photo.getBitmap();
Uri photoUri = photo.getImageUrl();
if (photoBitmap == null) {
if (photoUri == null) {
throw new FacebookException(
"SharePhoto does not have a Bitmap or ImageUrl specified");
}
if (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 validatePhotoForWebDialog(SharePhoto photo, Validator validator) {
if (photo == null) {
throw new FacebookException("Cannot share a null SharePhoto");
}
Uri imageUri = photo.getImageUrl();
if (imageUri == null || !Utility.isWebUri(imageUri)) {
throw new FacebookException(
"SharePhoto must have a non-null imageUrl set to the Uri of an image " +
"on the web");
}
}
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");
}
if (video.getLocalUrl() == null) {
throw new FacebookException("ShareVideo does not have a LocalUrl specified");
}
}
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((ShareOpenGraphValueContainer) openGraphAction, false);
}
private static void validateOpenGraphObject(
ShareOpenGraphObject openGraphObject,
Validator validator) {
if (openGraphObject == null) {
throw new FacebookException("Cannot share a null ShareOpenGraphObject");
}
validator.validate((ShareOpenGraphValueContainer) 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 SharePhotoContent photoContent) {
throw new FacebookException("Cannot share SharePhotoContent via web sharing dialogs");
}
@Override
public void validate(final ShareVideoContent videoContent) {
throw new FacebookException("Cannot share ShareVideoContent via web sharing dialogs");
}
@Override
public void validate(final SharePhoto photo) {
validatePhotoForWebDialog(photo, this);
}
}
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 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 boolean isOpenGraphContent() {
return isOpenGraphContent;
}
}
}