react-native-theoplayer 2.12.1 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.13.0] - 23-09-15
9
+
10
+ ### Fixed
11
+
12
+ - Fixed an issue where setting a new source on iOS, during DRM handling, would crash the application due to unsafe array access by different threads.
13
+
8
14
  ## [2.12.1] - 23-09-14
9
15
 
10
16
  ### Fixed
@@ -19,16 +19,15 @@ let BRIDGE_REQUEST_TIMEOUT = 10.0
19
19
  @objc(THEOplayerRCTContentProtectionAPI)
20
20
  class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
21
21
 
22
- private var buildIntegrationCompletions: [String:(Bool) -> Void] = [:] // [requestId : completion]
23
- private var certificateRequestCompletions: [String:(Data?, Error?) -> Void] = [:] // [requestId : completion]
24
- private var certificateResponseCompletions: [String:(Data?, Error?) -> Void] = [:] // [requestId : completion]
25
- private var licenseRequestCompletions: [String:(Data?, Error?) -> Void] = [:] // [requestId : completion]
26
- private var licenseResponseCompletions: [String:(Data?, Error?) -> Void] = [:] // [requestId : completion]
27
- private var extractFairplayCompletions: [String:(String, Error?) -> Void] = [:] // [requestId : completion]
28
- private var requestTimers: [String:Timer] = [:] // [requestId : Timer]
29
- private var requestIntegrationIds: [String:String] = [:] // [requestId : integrationId]
30
- private var requestKeySystemIds: [String:String] = [:] // [requestId : keySystemId]
31
-
22
+ private var buildIntegrationCompletions: THEOplayerRCTSafeMap<String, (Bool) -> Void> = THEOplayerRCTSafeMap<String, (Bool) -> Void>() // [requestId : completion]
23
+ private var certificateRequestCompletions: THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void> = THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void>() // [requestId : completion]
24
+ private var certificateResponseCompletions: THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void> = THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void>() // [requestId : completion]
25
+ private var licenseRequestCompletions: THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void> = THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void>() // [requestId : completion]
26
+ private var licenseResponseCompletions: THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void> = THEOplayerRCTSafeMap<String, (Data?, Error?) -> Void>() // [requestId : completion]
27
+ private var extractFairplayCompletions: THEOplayerRCTSafeMap<String, (String, Error?) -> Void> = THEOplayerRCTSafeMap<String, (String, Error?) -> Void>() // [requestId : completion]
28
+ private var requestTimers: THEOplayerRCTSafeMap<String, Timer> = THEOplayerRCTSafeMap<String, Timer>() // [requestId : Timer]
29
+ private var requestIntegrationIds: THEOplayerRCTSafeMap<String, String> = THEOplayerRCTSafeMap<String, String>() // [requestId : integrationId]
30
+ private var requestKeySystemIds: THEOplayerRCTSafeMap<String, String> = THEOplayerRCTSafeMap<String, String>() // [requestId : keySystemId]
32
31
 
33
32
  override static func moduleName() -> String! {
34
33
  return "ContentProtectionModule"
@@ -51,7 +50,7 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
51
50
  private func invalidateRequestWithId(_ requestId: String) {
52
51
  if let timer = self.requestTimers[requestId] {
53
52
  timer.invalidate()
54
- self.requestTimers.removeValue(forKey: requestId)
53
+ _ = self.requestTimers.removeValue(forKey: requestId)
55
54
  }
56
55
  }
57
56
 
@@ -68,7 +67,7 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
68
67
  self.requestTimers[requestId] = Timer.scheduledTimer(withTimeInterval: BRIDGE_REQUEST_TIMEOUT, repeats: false, block: { t in
69
68
  if DEBUG_CONTENT_PROTECTION_API { print(CPI_TAG, "Build timeout reached: removing completion for request with Id \(requestId)") }
70
69
  self.invalidateRequestWithId(requestId)
71
- self.buildIntegrationCompletions.removeValue(forKey: requestId)
70
+ _ = self.buildIntegrationCompletions.removeValue(forKey: requestId)
72
71
  })
73
72
  }
74
73
 
@@ -86,9 +85,9 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
86
85
  self.requestTimers[requestId] = Timer.scheduledTimer(withTimeInterval: BRIDGE_REQUEST_TIMEOUT, repeats: false, block: { t in
87
86
  if DEBUG_CONTENT_PROTECTION_API { print(CPI_TAG, "onCertificateRequest timeout reached: removing completion for request with Id \(requestId)") }
88
87
  self.invalidateRequestWithId(requestId)
89
- self.requestIntegrationIds.removeValue(forKey: requestId)
90
- self.requestKeySystemIds.removeValue(forKey: requestId)
91
- self.certificateRequestCompletions.removeValue(forKey: requestId)
88
+ _ = self.requestIntegrationIds.removeValue(forKey: requestId)
89
+ _ = self.requestKeySystemIds.removeValue(forKey: requestId)
90
+ _ = self.certificateRequestCompletions.removeValue(forKey: requestId)
92
91
  })
93
92
  }
94
93
 
@@ -104,7 +103,7 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
104
103
  self.requestTimers[requestId] = Timer.scheduledTimer(withTimeInterval: BRIDGE_REQUEST_TIMEOUT, repeats: false, block: { t in
105
104
  if DEBUG_CONTENT_PROTECTION_API { print(CPI_TAG, "onCertificateResponse timeout reached: removing completion for request with Id \(requestId)") }
106
105
  self.invalidateRequestWithId(requestId)
107
- self.certificateResponseCompletions.removeValue(forKey: requestId)
106
+ _ = self.certificateResponseCompletions.removeValue(forKey: requestId)
108
107
  })
109
108
  }
110
109
 
@@ -122,9 +121,9 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
122
121
  self.requestTimers[requestId] = Timer.scheduledTimer(withTimeInterval: BRIDGE_REQUEST_TIMEOUT, repeats: false, block: { t in
123
122
  if DEBUG_CONTENT_PROTECTION_API { print(CPI_TAG, "onLicenseRequest timeout reached: removing completion for request with Id \(requestId)") }
124
123
  self.invalidateRequestWithId(requestId)
125
- self.requestIntegrationIds.removeValue(forKey: requestId)
126
- self.requestKeySystemIds.removeValue(forKey: requestId)
127
- self.licenseRequestCompletions.removeValue(forKey: requestId)
124
+ _ = self.requestIntegrationIds.removeValue(forKey: requestId)
125
+ _ = self.requestKeySystemIds.removeValue(forKey: requestId)
126
+ _ = self.licenseRequestCompletions.removeValue(forKey: requestId)
128
127
  })
129
128
  }
130
129
 
@@ -140,7 +139,7 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
140
139
  self.requestTimers[requestId] = Timer.scheduledTimer(withTimeInterval: BRIDGE_REQUEST_TIMEOUT, repeats: false, block: { t in
141
140
  if DEBUG_CONTENT_PROTECTION_API { print(CPI_TAG, "onLicenseResponse timeout reached: removing completion for request with Id \(requestId)") }
142
141
  self.invalidateRequestWithId(requestId)
143
- self.licenseResponseCompletions.removeValue(forKey: requestId)
142
+ _ = self.licenseResponseCompletions.removeValue(forKey: requestId)
144
143
  })
145
144
  }
146
145
 
@@ -157,7 +156,7 @@ class THEOplayerRCTContentProtectionAPI: RCTEventEmitter {
157
156
  self.requestTimers[requestId] = Timer.scheduledTimer(withTimeInterval: BRIDGE_REQUEST_TIMEOUT, repeats: false, block: { t in
158
157
  if DEBUG_CONTENT_PROTECTION_API { print(CPI_TAG, "Fairplay contentId extraction timeout reached: removing completion for request with Id \(requestId)") }
159
158
  self.invalidateRequestWithId(requestId)
160
- self.extractFairplayCompletions.removeValue(forKey: requestId)
159
+ _ = self.extractFairplayCompletions.removeValue(forKey: requestId)
161
160
  })
162
161
  }
163
162
 
@@ -0,0 +1,64 @@
1
+ //
2
+ // THEOplayerRCTSafeMap.swift
3
+ // Theoplayer
4
+ //
5
+
6
+ import Foundation
7
+
8
+ class THEOplayerRCTSafeMap<K: Hashable,V>: Collection {
9
+ private var unsafeMap: [K: V]
10
+ private let concurrentQueue = DispatchQueue(label: "Safe Queue", attributes: .concurrent)
11
+
12
+ var startIndex: Dictionary<K, V>.Index {
13
+ self.concurrentQueue.sync {
14
+ return self.unsafeMap.startIndex
15
+ }
16
+ }
17
+
18
+ var endIndex: Dictionary<K, V>.Index {
19
+ self.concurrentQueue.sync {
20
+ return self.unsafeMap.endIndex
21
+ }
22
+ }
23
+
24
+ init(dict: [K: V] = [K: V]()) {
25
+ self.unsafeMap = dict
26
+ }
27
+
28
+ func index(after i: Dictionary<K, V>.Index) -> Dictionary<K, V>.Index {
29
+ self.concurrentQueue.sync {
30
+ return self.unsafeMap.index(after: i)
31
+ }
32
+ }
33
+
34
+ subscript(key: K) -> V? {
35
+ set(newValue) {
36
+ self.concurrentQueue.sync(flags: .barrier) {[weak self] in
37
+ self?.unsafeMap[key] = newValue
38
+ }
39
+ }
40
+ get {
41
+ self.concurrentQueue.sync {
42
+ return self.unsafeMap[key]
43
+ }
44
+ }
45
+ }
46
+
47
+ subscript(index: Dictionary<K, V>.Index) -> Dictionary<K, V>.Element {
48
+ self.concurrentQueue.sync {
49
+ return self.unsafeMap[index]
50
+ }
51
+ }
52
+
53
+ func removeValue(forKey key: K) -> V? {
54
+ self.concurrentQueue.sync(flags: .barrier) {[weak self] in
55
+ return self?.unsafeMap.removeValue(forKey: key)
56
+ }
57
+ }
58
+
59
+ func removeAll() {
60
+ self.concurrentQueue.sync(flags: .barrier) {[weak self] in
61
+ self?.unsafeMap.removeAll()
62
+ }
63
+ }
64
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-theoplayer",
3
- "version": "2.12.1",
3
+ "version": "2.13.0",
4
4
  "description": "A THEOplayer video component for react-native.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",