Skip to content

Commit 06ea89a

Browse files
authored
Merge pull request #53 from adobe/staging
Promote to main for release v3.0.1
2 parents 67edbd0 + 312c528 commit 06ea89a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+38304
-4921
lines changed

.swiftlint.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ disabled_rules: # rule identifiers to exclude from running
1414
- large_tuple
1515
- trailing_comma
1616
- type_body_length
17+
- weak_delegate
18+
- class_delegate_protocol
1719
opt_in_rules: # some rules are opt-in only
1820
- closure_end_indentation
1921
- convenience_type
@@ -33,6 +35,7 @@ opt_in_rules: # some rules are opt-in only
3335
- vertical_parameter_alignment_on_call
3436
excluded: # paths to ignore during linting
3537
- Carthage
38+
- AEPAssurance/UnitTests/
3639
- SampleApps/*/Pods
3740
- SampleApps/*/xdmlib
3841
- SampleApps/*/libs
@@ -48,4 +51,4 @@ identifier_name:
4851
- id
4952
- no
5053
- ok
51-
line_length: 1000
54+
line_length: 1000

AEPAssurance.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "AEPAssurance"
3-
s.version = "3.0.0"
3+
s.version = "3.0.1"
44
s.summary = "AEPAssurance SDK for Adobe Experience Platform Mobile SDK. Written and maintained by Adobe."
55

66
s.description = <<-DESC

AEPAssurance.xcodeproj/project.pbxproj

+55-7
Large diffs are not rendered by default.

AEPAssurance/Source/Assurance.swift

+12-9
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public class Assurance: NSObject, Extension {
2828

2929
let datastore = NamedCollectionDataStore(name: AssuranceConstants.EXTENSION_NAME)
3030
var assuranceSession: AssuranceSession?
31-
var shouldProcessEvents: Bool = true
3231
var timer: DispatchSourceTimer?
3332

3433
var sessionId: String? {
@@ -88,6 +87,7 @@ public class Assurance: NSObject, Extension {
8887
/// and do not turn on the unregister timer
8988
if connectedWebSocketURL != nil {
9089
shareState()
90+
Log.trace(label: AssuranceConstants.LOG_TAG, "Assurance Session was already connected during previous app launch. Attempting to reconnect. URL : \(String(describing: connectedWebSocketURL))")
9191
assuranceSession?.startSession()
9292
return
9393
}
@@ -127,6 +127,9 @@ public class Assurance: NSObject, Extension {
127127
return stateEvents
128128
}
129129

130+
// add the eventHub shared state data to the list of shared state events
131+
stateEvents.append(prepareSharedStateEvent(owner: AssuranceConstants.SharedStateName.EVENT_HUB, eventName: "EventHub State", stateContent: registeredExtension, stateType: AssuranceConstants.PayloadKey.SHARED_STATE_DATA))
132+
130133
for (extensionName, _) in extensionsMap {
131134
let friendlyName = getFriendlyExtensionName(extensionMap: extensionsMap, extensionName: extensionName)
132135
stateEvents.append(contentsOf: getStateForExtension(stateOwner: extensionName, friendlyName: friendlyName))
@@ -146,7 +149,7 @@ public class Assurance: NSObject, Extension {
146149
handleAssuranceRequestContent(event: event)
147150
}
148151

149-
if !shouldProcessEvents {
152+
guard let session = assuranceSession, session.canProcessSDKEvents else {
150153
return
151154
}
152155

@@ -157,7 +160,7 @@ public class Assurance: NSObject, Extension {
157160

158161
// forward all events to Assurance session
159162
let assuranceEvent = AssuranceEvent.from(event: event)
160-
assuranceSession?.sendEvent(assuranceEvent)
163+
session.sendEvent(assuranceEvent)
161164

162165
if event.isPlacesRequestEvent {
163166
handlePlacesRequest(event: event)
@@ -192,14 +195,15 @@ public class Assurance: NSObject, Extension {
192195
// Read the environment query parameter from the deeplink url
193196
let environmentString = deeplinkURL?.params[AssuranceConstants.Deeplink.ENVIRONMENT_KEY] ?? ""
194197

195-
// invalidate the timer
198+
// invalidate the timer
196199
invalidateTimer()
197200

198201
// save the environment and sessionID
199202
environment = AssuranceEnvironment.init(envString: environmentString)
200203
self.sessionId = sessionId
201204
shareState()
202-
shouldProcessEvents = true
205+
206+
Log.trace(label: AssuranceConstants.LOG_TAG, "Received sessionID, Initializing Assurance session. \(sessionId)")
203207
assuranceSession?.startSession()
204208
}
205209

@@ -232,7 +236,7 @@ public class Assurance: NSObject, Extension {
232236
}
233237
assuranceSession?.addClientLog("\t \(poiDictionary["regionname"] as? String ?? "Unknown")", visibility: .high)
234238
}
235-
assuranceSession?.addClientLog("Places - Found \(nearByPOIs.count) nearby POIs\(nearByPOIs.count > 0 ? " :" : ".")", visibility: .high)
239+
assuranceSession?.addClientLog("Places - Found \(nearByPOIs.count) nearby POIs\(!nearByPOIs.isEmpty ? " :" : ".")", visibility: .high)
236240
}
237241
}
238242

@@ -283,7 +287,7 @@ public class Assurance: NSObject, Extension {
283287
/// Start the shutdown timer in the background queue without blocking the current thread.
284288
/// If the timer get fired, then it shuts down the assurance extension.
285289
private func startShutDownTimer() {
286-
Log.debug(label: AssuranceConstants.LOG_TAG, "Assurance shutdown timer started. Waiting for 5 seconds to receive assurance session url.");
290+
Log.debug(label: AssuranceConstants.LOG_TAG, "Assurance shutdown timer started. Waiting for 5 seconds to receive assurance session url.")
287291
let queue = DispatchQueue.init(label: "com.adobe.assurance.shutdowntimer", qos: .background)
288292
timer = createDispatchTimer(queue: queue, block: {
289293
self.shutDownAssurance()
@@ -294,11 +298,10 @@ public class Assurance: NSObject, Extension {
294298
/// are listened by assurance extension
295299
/// @see readyForEvent
296300
private func shutDownAssurance() {
297-
shouldProcessEvents = false
298301
Log.debug(label: AssuranceConstants.LOG_TAG, "Timeout - Assurance extension did not receive session url. Shutting down from processing any further events.")
299302
invalidateTimer()
300303
Log.debug(label: AssuranceConstants.LOG_TAG, "Clearing the queued events and purging Assurance shared state.")
301-
self.assuranceSession?.clearQueueEvents()
304+
self.assuranceSession?.shutDownSession()
302305
clearState()
303306
}
304307

AEPAssurance/Source/AssuranceBlob.swift

+7-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import AEPServices
1414
import Foundation
1515

16-
struct AssuranceBlob {
16+
enum AssuranceBlob {
1717

1818
static let HTTPS_SCHEME = "https"
1919
static let HOST_FORMAT = "blob%@.griffon.adobe.com"
@@ -57,15 +57,18 @@ struct AssuranceBlob {
5757
let headers = [HttpConstants.HTTP_HEADER_KEY_ACCEPT: HttpConstants.HTTP_HEADER_CONTENT_TYPE_JSON_APPLICATION,
5858
HttpConstants.HTTP_HEADER_KEY_CONTENT_TYPE: HTTP_HEADER_VALUE_OCTET_STREAM,
5959
HTTP_HEADER_KEY_FILE_CONTENT_TYPE: contentType]
60-
61-
let networkRequest = NetworkRequest(url: components.url!,
60+
guard let url = components.url else {
61+
Log.warning(label: AssuranceConstants.LOG_TAG, "Invalid blob url. Unable to send blob data.")
62+
return
63+
}
64+
let networkRequest = NetworkRequest(url: url,
6265
httpMethod: HttpMethod.post,
6366
connectPayloadData: blob,
6467
httpHeaders: headers,
6568
connectTimeout: CONNECTION_TIMEOUT,
6669
readTimeout: CONNECTION_TIMEOUT)
6770

68-
Log.debug(label: AssuranceConstants.LOG_TAG, "Uploading blob data to URL : \(components.url!.absoluteString)")
71+
Log.debug(label: AssuranceConstants.LOG_TAG, "Uploading blob data to URL : \(url.absoluteString)")
6972
ServiceProvider.shared.networkService.connectAsync(networkRequest: networkRequest, completionHandler: { connection in
7073
handleNetworkResponse(connection: connection, callback: callback)
7174
})

AEPAssurance/Source/AssuranceClientInfo.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import CoreLocation
1515
import Foundation
1616
import UIKit
1717

18-
struct AssuranceClientInfo {
18+
enum AssuranceClientInfo {
1919

2020
static let PLATFORM_NAME = "Canonical platform name"
2121
static let DEVICE_NAME = "Device name"
@@ -54,7 +54,7 @@ struct AssuranceClientInfo {
5454
return appSettingsInDictionary
5555
}
5656

57-
///- Returns: A `Dictionary` with the required device information
57+
/// - Returns: A `Dictionary` with the required device information
5858
private static func readDeviceInfo() -> [String: Any] {
5959
let systemInfoService = ServiceProvider.shared.systemInfoService
6060

@@ -77,7 +77,7 @@ struct AssuranceClientInfo {
7777
/// Battery level ranges from 0 (fully discharged) to 100 (fully charged).
7878
/// For simulator where the battery levels are not available -1 is returned.
7979
///
80-
///- Returns: An `Int` representing the battery level of the device
80+
/// - Returns: An `Int` representing the battery level of the device
8181
private static func getBatteryLevel() -> Int {
8282
let batteryPercentage = Int(UIDevice.current.batteryLevel * 100)
8383
return (batteryPercentage) > 0 ? batteryPercentage : -1

AEPAssurance/Source/AssuranceConnectionError.swift

+7-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum AssuranceConnectionError {
2222
case orgIDMismatch
2323
case connectionLimit
2424
case eventLimit
25+
case deletedSession
2526
case clientError
2627
case userCancelled
2728

@@ -40,11 +41,11 @@ enum AssuranceConnectionError {
4041
return ("Socket Connection Error",
4142
"Unable to form a valid socket URL for connection.", false)
4243
case .noOrgId:
43-
return ("Invalid Launch & SDK Configuration",
44-
"The Experience Cloud Org identifier is unavailable from SDK configuration. Please ensure the Launch mobile property is properly configured.", false)
44+
return (" Invalid Mobile SDK Configuration",
45+
"The Experience Cloud organization identifier is unavailable. Ensure SDK configuration is setup correctly. See documentation for more detail.", false)
4546
case .orgIDMismatch:
4647
return ("Unauthorized Access",
47-
"The Experience Cloud organization for this Launch Property does not match that of the AEP Assurance session", false)
48+
"The Experience Cloud organization identifier does not match with that of the Assurance session. Ensure the right Experience Cloud organization is being used. See documentation for more detail.", false)
4849
case .connectionLimit:
4950
return ("Connection Limit Reached",
5051
"You have reached the maximum number of connected device (50) allowed to a session.", false)
@@ -53,6 +54,9 @@ enum AssuranceConnectionError {
5354
"You have reached the maximum number of events (10k) that can be sent per minute.", false)
5455
// todo immediate: check with the team on better description.
5556
// todo later: have griffon server return error description and how to solve... Same for connection & event limit errors
57+
case .deletedSession:
58+
return ("Session Deleted",
59+
"You attempted to connect to a deleted session.", false)
5660
case .clientError:
5761
return ("Client Disconnected",
5862
"This client has been disconnected due to an unexpected error. Error Code 4400.", false)

AEPAssurance/Source/AssuranceConstants.swift

+36-18
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Foundation
1515
enum AssuranceConstants {
1616
static let EXTENSION_NAME = "com.adobe.assurance"
1717
static let FRIENDLY_NAME = "Assurance"
18-
static let EXTENSION_VERSION = "3.0.0"
18+
static let EXTENSION_VERSION = "3.0.1"
1919
static let LOG_TAG = FRIENDLY_NAME
2020
static let DEFAULT_ENVIRONMENT = AssuranceEnvironment.prod
2121

@@ -38,19 +38,19 @@ enum AssuranceConstants {
3838
}
3939

4040
enum SDKEventName {
41-
static let SHARED_STATE_CHANGE = "Shared state change"
42-
static let XDM_SHARED_STATE_CHANGE = "Shared state change (XDM)"
41+
static let SHARED_STATE_CHANGE = "Shared state change"
42+
static let XDM_SHARED_STATE_CHANGE = "Shared state change (XDM)"
4343
}
4444

4545
enum SDKEventType {
4646
static let ASSURANCE = "com.adobe.eventType.assurance"
4747
}
4848

4949
enum PluginFakeEvent {
50-
static let NAME = "eventName"
51-
static let TYPE = "eventType"
52-
static let SOURCE = "eventSource"
53-
static let DATA = "eventData"
50+
static let NAME = "eventName"
51+
static let TYPE = "eventType"
52+
static let SOURCE = "eventSource"
53+
static let DATA = "eventData"
5454
}
5555

5656
// todo verify the impact of making these keys AEPExtensionEvent*
@@ -59,8 +59,8 @@ enum AssuranceConstants {
5959
static let TYPE = "ACPExtensionEventType"
6060
static let SOURCE = "ACPExtensionEventSource"
6161
static let DATA = "ACPExtensionEventData"
62-
static let TIMESTAMP = "ACPExtensionEventTimestamp"
63-
static let NUMBER = "ACPExtensionEventNumber"
62+
static let TIMESTAMP = "ACPExtensionEventTimestamp"
63+
static let NUMBER = "ACPExtensionEventNumber"
6464
static let UNIQUE_IDENTIFIER = "ACPExtensionEventUniqueIdentifier"
6565
static let RESPONSE_IDENTIFIER = "ACPExtensionEventResponseIdentifier" // todo new key introduced : convey to UI team
6666
}
@@ -106,21 +106,21 @@ enum AssuranceConstants {
106106
enum HTMLURLPath {
107107
static let CANCEL = "cancel"
108108
static let CONFIRM = "confirm"
109-
static let DISCONNECT = "disconnect"
109+
static let DISCONNECT = "disconnect"
110110
}
111111

112112
enum ClientInfoKeys {
113-
static let TYPE = "type"
114-
static let VERSION = "version"
115-
static let DEVICE_INFO = "deviceInfo"
116-
static let APP_SETTINGS = "appSettings"
113+
static let TYPE = "type"
114+
static let VERSION = "version"
115+
static let DEVICE_INFO = "deviceInfo"
116+
static let APP_SETTINGS = "appSettings"
117117
}
118118

119119
enum CommandType {
120-
static let START_EVENT_FORWARDING = "startEventForwarding"
121-
static let CONFIG_UPDATE = "configUpdate"
122-
static let FAKE_EVENT = "fakeEvent"
123-
static let SCREENSHOT = "screenshot"
120+
static let START_EVENT_FORWARDING = "startEventForwarding"
121+
static let CONFIG_UPDATE = "configUpdate"
122+
static let FAKE_EVENT = "fakeEvent"
123+
static let SCREENSHOT = "screenshot"
124124
static let LOG_FORWARDING = "logForwarding"
125125
static let WILDCARD = "wildcard"
126126
}
@@ -131,6 +131,7 @@ enum AssuranceConstants {
131131
static let ORG_MISMATCH = 4900
132132
static let CONNECTION_LIMIT = 4901
133133
static let EVENTS_LIMIT = 4902
134+
static let DELETED_SESSION = 4903
134135
static let CLIENT_ERROR = 4400
135136
}
136137

@@ -158,4 +159,21 @@ enum AssuranceConstants {
158159
static let NEARBY_POI = "nearbypois"
159160
}
160161
}
162+
163+
enum AssuranceEvent {
164+
/// The maximum size of an event that can get through the socket is 32KB.
165+
/// The factor 0.75 is introduced to accommodate blowing up of size due to the mandatory base64 encoding of AssuranceEvent before sending through the socket.
166+
static let SIZE_LIMIT = (Int) ((32 * 1024) * 0.75)
167+
168+
enum PayloadKey {
169+
static let CHUNK_DATA = "chunkData"
170+
}
171+
172+
enum MetadataKey {
173+
static let CHUNK_ID = "chunkId"
174+
static let CHUNK_SEQUENCE = "chunkSequenceNumber"
175+
static let CHUNK_TOTAL = "chunkTotal"
176+
}
177+
}
178+
161179
}

AEPAssurance/Source/AssuranceEvent.swift

+15-1
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ import AEPCore
1414
import AEPServices
1515
import Foundation
1616

17+
/// Event object used to transport data to/from Assurance server.
18+
///
19+
/// This object is intentionally opaque (internal). If this needs to be public,
20+
/// refactor this class to reflect a builder pattern enforcing size limits on
21+
/// constituents of the AssuranceEvent like metadata.
1722
struct AssuranceEvent: Codable {
1823
var eventID: String = UUID().uuidString
1924
var vendor: String
2025
var type: String
2126
var payload: [String: AnyCodable]?
2227
var eventNumber: Int32?
2328
var timestamp: Date?
29+
var metadata: [String: AnyCodable]?
2430

2531
/// Decodes a JSON data into a `AssuranceEvent`
2632
///
@@ -91,12 +97,13 @@ struct AssuranceEvent: Codable {
9197
/// - payload: A dictionary representing the payload to be sent wrapped in the event. This will be serialized into JSON in the transportation process
9298
/// - timestamp: optional argument representing the time original event was created. If not provided current time is taken
9399
/// - vendor: vendor for the created `AssuranceEvent` defaults to "com.adobe.griffon.mobile".
94-
init(type: String, payload: [String: AnyCodable]?, timestamp: Date = Date(), vendor: String = AssuranceConstants.Vendor.MOBILE) {
100+
init(type: String, payload: [String: AnyCodable]?, timestamp: Date = Date(), vendor: String = AssuranceConstants.Vendor.MOBILE, metadata: [String: AnyCodable]? = nil) {
95101
self.type = type
96102
self.payload = payload
97103
self.timestamp = timestamp
98104
self.vendor = vendor
99105
self.eventNumber = AssuranceEvent.generateEventNumber()
106+
self.metadata = metadata
100107
}
101108

102109
/// Returns the type of the command. Applies only for command events. This method returns nil for all other `AssuranceEvent`s.
@@ -157,8 +164,15 @@ struct AssuranceEvent: Codable {
157164
" payload: \(PrettyDictionary.prettify(payload))\n" +
158165
" eventNumber: \(String(describing: eventNumber))\n" +
159166
" timestamp: \(String(describing: timestamp?.description))\n" +
167+
" metadata: \(PrettyDictionary.prettify(metadata))\n" +
160168
"]"
161169
// swiftformat:enable indent
162170
}
163171

172+
var jsonData: Data {
173+
let encoder = JSONEncoder()
174+
encoder.dateEncodingStrategy = .millisecondsSince1970
175+
return (try? encoder.encode(self)) ?? Data()
176+
}
177+
164178
}

0 commit comments

Comments
 (0)