Skip to content

Commit

Permalink
Add privacy manifest and related changes to ShareKit
Browse files Browse the repository at this point in the history
Reviewed By: ryantobinmeta

Differential Revision: D54609966

fbshipit-source-id: 78d03a58724659357f24e5ac9825f2c6b83142e9
  • Loading branch information
Yuriy Tol authored and facebook-github-bot committed Mar 11, 2024
1 parent db78ef7 commit 86105db
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 30 deletions.
2 changes: 1 addition & 1 deletion FBSDKShareKit/FBSDKShareKit/Content/_ShareUtility.swift
Expand Up @@ -163,7 +163,7 @@ extension _ShareUtility: ShareUtilityProtocol {
guard let linkContent = content as? ShareLinkContent else { return nil }

let parameters: [String: Any?] = [
"link": linkContent.contentURL,
"href": linkContent.contentURL?.absoluteString,
"quote": linkContent.quote,
"hashtag": hashtagString(from: linkContent.hashtag),
"place": content.placeID,
Expand Down
52 changes: 52 additions & 0 deletions FBSDKShareKit/FBSDKShareKit/PrivacyInfo.xcprivacy
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeOtherDataTypes</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeCrashData</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<true/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeThirdPartyAdvertising</string>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyTracking</key>
<true/>
<key>NSPrivacyTrackingDomains</key>
<array>
<string>ep1.facebook.com</string>
</array>
</dict>
</plist>
91 changes: 67 additions & 24 deletions FBSDKShareKit/FBSDKShareKit/UserInterface/ShareDialog.swift
Expand Up @@ -20,7 +20,7 @@ public class ShareDialog: NSObject, SharingDialog { // swiftlint:disable:this pr
private struct UnknownValidationError: Error {}
private struct BridgeRequestCreationError: Error {}

private static let feedMethodName = "feed"
private static let feedMethodName = "share"

private static var hasValidatedURLSchemeRegistration = false
private static var temporaryDirectory = URL(
Expand Down Expand Up @@ -172,7 +172,12 @@ extension ShareDialog {

public var canShow: Bool {
guard shareContent != nil else {
return canShowWithoutContent
do {
try validateAdvertiserTrackingPermission(mode: mode)
return canShowWithoutContent
} catch {
return false
}
}

do {
Expand Down Expand Up @@ -430,7 +435,7 @@ extension ShareDialog {
throw MissingContentError()
}

try validateShareContentForBrowser()
try validateShareContentForShareWebDialog(mode: .browser)

if let photoContent = content as? SharePhotoContent,
photoContentHasAtLeastOneImage(photoContent) {
Expand Down Expand Up @@ -490,7 +495,7 @@ extension ShareDialog {
}

private func showFeedBrowser() throws {
try validateShareContentForFeed()
try validateShareContentForFeedWebDialog(mode: .feedBrowser)
let dependencies = try Self.getDependencies()

guard let content = shareContent else {
Expand Down Expand Up @@ -525,7 +530,7 @@ extension ShareDialog {
}

private func showFeedWeb() throws {
try validateShareContentForFeed()
try validateShareContentForFeedWebDialog(mode: .feedWeb)
let dependencies = try Self.getDependencies()

guard let content = shareContent else {
Expand Down Expand Up @@ -680,7 +685,7 @@ extension ShareDialog {
}

private func showWeb() throws {
try validateShareContentForBrowser(options: .photoImageURL)
try validateShareContentForShareWebDialog(mode: .web, options: .photoImageURL)
let dependencies = try Self.getDependencies()

guard let content = shareContent else {
Expand Down Expand Up @@ -748,12 +753,13 @@ extension ShareDialog {
case .shareSheet:
try validateShareContentForShareSheet()
case .browser:
try validateShareContentForBrowser()
try validateShareContentForShareWebDialog(mode: mode)
case .web:
try validateShareContentForBrowser(options: .photoImageURL)
case .feedBrowser,
.feedWeb:
try validateShareContentForFeed()
try validateShareContentForShareWebDialog(mode: mode, options: .photoImageURL)
case .feedBrowser:
try validateShareContentForFeedWebDialog(mode: mode)
case .feedWeb:
try validateShareContentForFeedWebDialog(mode: mode)
}
}

Expand All @@ -773,23 +779,29 @@ extension ShareDialog {
}

do {
try validateShareContentForFeed()
try validateShareContentForFeedWebDialog(mode: .automatic)
return
} catch {}

try validateShareContentForBrowser()
try validateShareContentForShareWebDialog(mode: .automatic)
}

private func validateShareContentForBrowser(options bridgeOptions: ShareBridgeOptions = []) throws {
private func validateShareContentForShareWebDialog(
mode: Mode,
options bridgeOptions: ShareBridgeOptions = []
) throws {
let dependencies = try Self.getDependencies()

try validateAdvertiserTrackingPermission(mode: mode)

guard let content = shareContent else {
throw MissingContentError()
}

let errorFactory = dependencies.errorFactory
if let linkContent = content as? ShareLinkContent,
linkContent.contentURL == nil {
throw dependencies.errorFactory.invalidArgumentError(
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "shareContent",
value: linkContent,
Expand All @@ -799,7 +811,7 @@ extension ShareDialog {
}

guard !(shareContent is ShareCameraEffectContent) else {
throw dependencies.errorFactory.invalidArgumentError(
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "shareContent",
value: shareContent,
Expand All @@ -812,7 +824,7 @@ extension ShareDialog {

if flags.containsPhotos {
guard AccessToken.current != nil else {
throw dependencies.errorFactory.invalidArgumentError(
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "shareContent",
value: content,
Expand All @@ -824,7 +836,7 @@ extension ShareDialog {
if let photo = content as? SharePhotoContent {
try photo.validate(options: bridgeOptions)
} else {
throw dependencies.errorFactory.invalidArgumentError(
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "shareContent",
value: content,
Expand All @@ -835,18 +847,18 @@ extension ShareDialog {
}

if flags.containsVideos {
throw dependencies.errorFactory.invalidArgumentError(
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "shareContent",
value: content,
message: "video sharing through the browser is not supported.",
message: "Video sharing through the browser is not supported.",
underlyingError: nil
)
}

if flags.containsMedia,
bridgeOptions == .photoImageURL { // a web-based URL is required
throw dependencies.errorFactory.invalidArgumentError(
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "shareContent",
value: content,
Expand All @@ -856,8 +868,11 @@ extension ShareDialog {
}
}

private func validateShareContentForFeed() throws {
let errorFactory = try Self.getDependencies().errorFactory
private func validateShareContentForFeedWebDialog(mode: Mode) throws {
let dependencies = try Self.getDependencies()
let errorFactory = dependencies.errorFactory

try validateAdvertiserTrackingPermission(mode: mode)

if let linkContent = shareContent as? ShareLinkContent {
if linkContent.contentURL == nil {
Expand All @@ -874,7 +889,7 @@ extension ShareDialog {
domain: ShareErrorDomain,
name: "shareContent",
value: shareContent,
message: "Feed share dialogs support ShareLinkContent.",
message: "Feed share dialogs support ShareLinkContent only.",
underlyingError: nil
)
}
Expand Down Expand Up @@ -965,6 +980,34 @@ extension ShareDialog {
}
}

private func validateAdvertiserTrackingPermission(mode: Mode) throws {
let dependencies = try Self.getDependencies()
let errorFactory = dependencies.errorFactory

let isTrackingEnabled = dependencies.settings.isAdvertiserTrackingEnabled == true
let isWebViewsMode = mode == .feedWeb || mode == .web
guard !isWebViewsMode || isTrackingEnabled else {
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "unavailableDestination",
value: shareContent,
message: "Tracking permission is required to share to web destination.",
underlyingError: nil
)
}

let isBrowsersMode = mode == .browser || mode == .feedBrowser
guard !isBrowsersMode || !(shareContent is SharePhotoContent) || isTrackingEnabled else {
throw errorFactory.invalidArgumentError(
domain: ShareErrorDomain,
name: "unavailableDestination",
value: shareContent,
message: "Valid access token is required to share photos with browser destination.",
underlyingError: nil
)
}
}

private func invokeDelegateDidCancel() {
AppEvents.shared.logInternalEvent(
.shareDialogResult,
Expand Down
15 changes: 15 additions & 0 deletions FBSDKShareKit/FBSDKShareKit/UserInterface/ShareDialogMode.swift
Expand Up @@ -30,12 +30,27 @@ extension ShareDialog {
case browser

/// Displays the dialog in a WKWebView within the app.
@available(
*,
deprecated,
message: "The web sharing mode is deprecated. Consider using automatic sharing mode instead."
)
case web

/// Displays the feed dialog in Safari.
@available(
*,
deprecated,
message: "The feed browser sharing mode is deprecated. Consider using automatic or browser sharing modes instead."
)
case feedBrowser

/// Displays the feed dialog in a WKWebView within the app.
@available(
*,
deprecated,
message: "The feed web sharing mode is deprecated. Consider using automatic sharing mode instead."
)
case feedWeb

/// The string description
Expand Down

0 comments on commit 86105db

Please sign in to comment.