Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SP-8288 ott unexpected response message endpoint #353

Merged
merged 8 commits into from
Jan 26, 2022
44 changes: 36 additions & 8 deletions ConsentViewController/Classes/SPConsentManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ import UIKit
var propertyId: Int? { storage.propertyId }
var propertyIdString: String { propertyId != nil ? String(propertyId!) : "" }
var iOSMessagePartitionUUID: String?
var messagesToShow = 0
var responsesToReceive = 0

init(
accountId: Int,
Expand All @@ -83,6 +85,12 @@ import UIKit
self.deviceManager = deviceManager
}

func handleSDKDone() {
if messagesToShow == 0, responsesToReceive == 0 {
delegate?.onSPFinished?(userData: userData)
}
}

func renderNextMessageIfAny() {
DispatchQueue.main.async { [weak self] in
if let ui = self?.messageControllersStack.popLast() {
Expand Down Expand Up @@ -158,9 +166,11 @@ import UIKit
}

func report(action: SPAction) {
responsesToReceive += 1
switch action.campaignType {
case .ccpa:
spClient.postCCPAAction(authId: authId, action: action, localState: storage.localState, idfaStatus: idfaStatus) { [weak self] result in
self?.responsesToReceive -= 1
switch result {
case .success((let localState, let consents)):
let userData = SPUserData(
Expand All @@ -172,13 +182,14 @@ import UIKit
userData: userData,
propertyId: self?.propertyId
)
self?.delegate?.onConsentReady?(userData: userData)
self?.onConsentReceived()
case .failure(let error):
self?.onError(error)
}
}
case .gdpr:
spClient.postGDPRAction(authId: authId, action: action, localState: storage.localState, idfaStatus: idfaStatus) { [weak self] result in
self?.responsesToReceive -= 1
switch result {
case .success((let localState, let consents)):
let userData = SPUserData(
Expand All @@ -190,7 +201,7 @@ import UIKit
userData: userData,
propertyId: self?.propertyId
)
self?.delegate?.onConsentReady?(userData: userData)
self?.onConsentReceived()
case .failure(let error):
self?.onError(error)
}
Expand All @@ -216,6 +227,11 @@ import UIKit
}
#endif

func onConsentReceived() {
delegate?.onConsentReady?(userData: storage.userData)
handleSDKDone()
}

public func onError(_ error: SPError) {
spClient.errorMetrics(
error,
Expand Down Expand Up @@ -248,13 +264,15 @@ import UIKit

public func loadMessage(forAuthId authId: String? = nil) {
self.authId = authId
responsesToReceive += 1
spClient.getMessages(
campaigns: campaigns,
authId: authId,
localState: storage.localState,
idfaStaus: idfaStatus,
consentLanguage: messageLanguage
) { [weak self] result in
self?.responsesToReceive -= 1
switch result {
case .success(let messagesResponse):
self?.storeData(
Expand All @@ -278,8 +296,9 @@ import UIKit
$0.type
)}
.reversed()
self?.messagesToShow = self?.messageControllersStack.count ?? 0
if self?.messageControllersStack.isEmpty ?? true {
self?.delegate?.onConsentReady?(userData: self?.storage.userData ?? SPUserData())
self?.onConsentReceived()
} else {
self?.renderNextMessageIfAny()
}
Expand All @@ -290,6 +309,7 @@ import UIKit
}

public func loadGDPRPrivacyManager(withId id: String, tab: SPPrivacyManagerTab = .Default) {
messagesToShow += 1
#if os(iOS)
guard let pmUrl = Constants.GDPR_PM_URL.appendQueryItems([
"message_id": id,
Expand All @@ -310,7 +330,6 @@ import UIKit
self?.onError(SPError())
return
}

let pmViewController = SPGDPRNativePrivacyManagerViewController(
messageId: id,
campaignType: .gdpr,
Expand All @@ -329,6 +348,7 @@ import UIKit
}

public func loadCCPAPrivacyManager(withId id: String, tab: SPPrivacyManagerTab = .Default) {
messagesToShow += 1
#if os(iOS)
guard let pmUrl = Constants.CCPA_PM_URL.appendQueryItems([
"message_id": id,
Expand Down Expand Up @@ -414,6 +434,8 @@ extension SPConsentManager: SPMessageUIDelegate {
public func finished(_ vcFinished: UIViewController) {
DispatchQueue.main.async { [weak self] in
self?.delegate?.onSPUIFinished(vcFinished)
self?.messagesToShow -= 1
self?.handleSDKDone()
}
}

Expand All @@ -439,7 +461,7 @@ extension SPConsentManager: SPMessageUIDelegate {
}

public func action(_ action: SPAction, from controller: UIViewController) {
delegate?.onAction(action, from: controller)
onAction(action, from: controller)
switch action.type {
case .AcceptAll, .RejectAll, .SaveAndExit:
report(action: action)
Expand All @@ -460,19 +482,25 @@ extension SPConsentManager: SPMessageUIDelegate {
SPIDFAStatus.requestAuthorisation { [weak self] status in
let spController = controller as? SPMessageViewController
self?.reportIdfaStatus(status: status, messageId: Int(spController?.messageId ?? ""))
self?.nextMessageIfAny(controller)
if status == .accepted {
action.type = .IDFAAccepted
self?.delegate?.onAction(action, from: controller)
self?.onAction(action, from: controller)
} else if status == .denied {
action.type = .IDFADenied
self?.delegate?.onAction(action, from: controller)
self?.onAction(action, from: controller)
}
self?.nextMessageIfAny(controller)
}
default:
nextMessageIfAny(controller)
}
}

func onAction(_ action: SPAction, from controller: UIViewController) {
DispatchQueue.main.async { [weak self] in
self?.delegate?.onAction(action, from: controller)
}
}
}

typealias SPGDPRSecondLayerHandler = (Result<GDPRPrivacyManagerViewResponse, SPError>) -> Void
Expand Down
7 changes: 6 additions & 1 deletion ConsentViewController/Classes/SPDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ import UIKit

/// called after the user takes an action and the SDK receives consent data back from the server
/// - Parameters:
/// - consents: is the consent profile
/// - userData: is the consent profile
@objc optional func onConsentReady(userData: SPUserData)

/// called when the SDK is done. That will happen if there's no more messages to be displayed and all network requests are done.
/// - Parameters:
/// - userData: is the consent profile
@objc optional func onSPFinished(userData: SPUserData)

/// called if something goes wrong during the entire lifecycle of the SDK
@objc optional func onError(error: SPError)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,35 @@ struct GDPRVendor: Decodable {
let vendorType: VendorType
let consentCategories, legIntCategories: [Category]
let iabSpecialPurposes, iabFeatures, iabSpecialFeatures: [String]

enum Keys: String, CodingKey {
case policyUrl, vendorId, name
case iabId
case iabSpecialPurposes, iabFeatures, iabSpecialFeatures
case description, cookieHeader
case vendorType
case consentCategories, legIntCategories
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Keys.self)
do {
policyUrl = try container.decodeIfPresent(URL.self, forKey: .policyUrl)
} catch {
policyUrl = nil
}
iabId = try container.decodeIfPresent(Int.self, forKey: .iabId)
vendorId = try container.decode(String.self, forKey: .vendorId)
name = try container.decode(String.self, forKey: .name)
iabSpecialPurposes = try container.decode([String].self, forKey: .iabSpecialPurposes)
iabFeatures = try container.decode([String].self, forKey: .iabFeatures)
iabSpecialFeatures = try container.decode([String].self, forKey: .iabSpecialFeatures)
description = try container.decodeIfPresent(String.self, forKey: .description)
cookieHeader = try container.decodeIfPresent(String.self, forKey: .cookieHeader)
vendorType = try container.decode(VendorType.self, forKey: .vendorType)
consentCategories = try container.decode([Category].self, forKey: .consentCategories)
legIntCategories = try container.decode([Category].self, forKey: .legIntCategories)
}
}

extension GDPRVendor: Identifiable, Equatable, Hashable {
Expand Down Expand Up @@ -81,7 +110,11 @@ extension CCPAVendor: Decodable {
let container = try decoder.container(keyedBy: Keys.self)
_id = try container.decode(String.self, forKey: ._id)
name = try container.decode(String.self, forKey: .name)
policyUrl = try container.decodeIfPresent(URL.self, forKey: .policyUrl)
do {
policyUrl = try container.decodeIfPresent(URL.self, forKey: .policyUrl)
} catch {
policyUrl = nil
}
nullablePurposes = try container.decodeIfPresent([String?].self, forKey: .nullablePurposes)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ import Foundation
let vendorId: String?
let policyUrl: URL?
let vendorType: GDPRVendor.VendorType?

enum Keys: String, CodingKey {
case name
case vendorId
case policyUrl
case vendorType
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Keys.self)
do {
policyUrl = try container.decodeIfPresent(URL.self, forKey: .policyUrl)
} catch {
policyUrl = nil
}
vendorId = try container.decodeIfPresent(String.self, forKey: .vendorId)
name = try container.decode(String.self, forKey: .name)
vendorType = try container.decodeIfPresent(GDPRVendor.VendorType.self, forKey: .vendorType) }
}

let iabId: Int?
Expand Down
4 changes: 4 additions & 0 deletions Example/ConsentViewController/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ extension ViewController: SPDelegate {
updatePMButtons(ccpaApplies: consentManager.ccpaApplies, gdprApplies: consentManager.gdprApplies)
}

func onSPFinished(userData: SPUserData) {
print("SDK DONE")
}

func onError(error: SPError) {
print("Something went wrong: ", error)
}
Expand Down