From 81e7eef64ead06808561b612cc134ed29f5fb5cc Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Fri, 13 Nov 2020 18:49:23 +0900 Subject: [PATCH 01/11] updates to code to allow full native drm code to run --- Video.js | 2 +- ios/Video/RCTVideo.m | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Video.js b/Video.js index 6b84021f3f..94f1c3de0a 100644 --- a/Video.js +++ b/Video.js @@ -237,7 +237,7 @@ export default class Video extends Component { if (this.props.drm && this.props.drm.getLicense instanceof Function) { const data = event.nativeEvent; if (data && data.spc) { - const getLicenseOverride = this.props.drm.getLicense(data.spc, data.contentId, data.spcBase64, this.props); + const getLicenseOverride = this.props.drm.getLicense(data.spc, data.contentId, data.licenseUrl); //test const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not. getLicensePromise.then((result => { if (result !== undefined) { diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 8780f48f68..4ea6025473 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1764,7 +1764,7 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { } _loadingRequest = loadingRequest; NSURL *url = loadingRequest.request.URL; - NSString *contentId = url.host; + NSString *contentId = [url.absoluteString stringByReplacingOccurrencesOfString:@"skd://" withString:@""]; if (self->_drm != nil) { NSString *contentIdOverride = (NSString *)[self->_drm objectForKey:@"contentId"]; if (contentIdOverride != nil) { @@ -1782,7 +1782,7 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { } if (certificateData != nil) { - NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; + NSData *contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; if (dataRequest != nil) { NSError *spcError = nil; @@ -1794,14 +1794,22 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { self->_requestingCertificateErrored = YES; } if (spcData != nil) { + NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; if(self.onGetLicense) { - NSString *spcStr = [[NSString alloc] initWithData:spcData encoding:NSASCIIStringEncoding]; self->_requestingCertificate = YES; - self.onGetLicense(@{@"spc": spcStr, + self.onGetLicense(@{@"licenseUrl": licenseServer, @"contentId": contentId, - @"spcBase64": [[[NSData alloc] initWithBase64EncodedData:certificateData options:NSDataBase64DecodingIgnoreUnknownCharacters] base64EncodedStringWithOptions:0], + @"spc": spcEncoded, @"target": self.reactTag}); } else if(licenseServer != nil) { + NSData *responseData = nil; + NSTimeInterval expiryDuration = 0.0; + + NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); + NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; + + NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; [request setURL:[NSURL URLWithString:licenseServer]]; @@ -1813,9 +1821,8 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [request setValue:value forHTTPHeaderField:key]; } } - // - [request setHTTPBody: spcData]; + [request setHTTPBody: postData]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -1838,7 +1845,8 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } else if (data != nil) { - [dataRequest respondWithData:data]; + NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + [dataRequest respondWithData:decodedData]; [loadingRequest finishLoading]; } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" @@ -1852,7 +1860,7 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } - + } }]; [postDataTask resume]; From 0b2d96f3073aed2514f5d8081025a06c981239cd Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Fri, 13 Nov 2020 18:58:31 +0900 Subject: [PATCH 02/11] cleanup --- ios/Video/RCTVideo.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 4ea6025473..7ec65fa09a 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1802,12 +1802,9 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { @"spc": spcEncoded, @"target": self.reactTag}); } else if(licenseServer != nil) { - NSData *responseData = nil; - NSTimeInterval expiryDuration = 0.0; NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; - NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; From 10d31b73b46e27e8bddf4747a1b68d3979a86941 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Fri, 13 Nov 2020 19:06:54 +0900 Subject: [PATCH 03/11] cleanup --- Video.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Video.js b/Video.js index 94f1c3de0a..0e6895c87d 100644 --- a/Video.js +++ b/Video.js @@ -237,7 +237,7 @@ export default class Video extends Component { if (this.props.drm && this.props.drm.getLicense instanceof Function) { const data = event.nativeEvent; if (data && data.spc) { - const getLicenseOverride = this.props.drm.getLicense(data.spc, data.contentId, data.licenseUrl); //test + const getLicenseOverride = this.props.drm.getLicense(data.spc, data.contentId, data.licenseUrl); const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not. getLicensePromise.then((result => { if (result !== undefined) { From 6cd7ac168357ff406e5b031321e52c7ec82b8e02 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Fri, 13 Nov 2020 19:48:02 +0900 Subject: [PATCH 04/11] cleanup --- ios/Video/RCTVideo.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 7ec65fa09a..f1d29f129e 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1842,8 +1842,9 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } else if (data != nil) { - NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; - [dataRequest respondWithData:decodedData]; + // NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + // [dataRequest respondWithData:decodedData]; + [dataRequest respondWithData:data]; [loadingRequest finishLoading]; } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" From 10a5c1f6a67e1184c144d93683022cdd3fdd46b1 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Mon, 16 Nov 2020 20:13:55 +0900 Subject: [PATCH 05/11] add back decoded data passed to player --- ios/Video/RCTVideo.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index f1d29f129e..7ec65fa09a 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1842,9 +1842,8 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } else if (data != nil) { - // NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; - // [dataRequest respondWithData:decodedData]; - [dataRequest respondWithData:data]; + NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + [dataRequest respondWithData:decodedData]; [loadingRequest finishLoading]; } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" From 02884ee97ef69d0e010d870918abfd6c0114270e Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Thu, 3 Dec 2020 20:26:37 +0900 Subject: [PATCH 06/11] separate logic for getLicense js handling and native handling --- ios/Video/RCTVideo.m | 210 +++++++++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 86 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 7ec65fa09a..25e096c067 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1782,111 +1782,149 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { } if (certificateData != nil) { - NSData *contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; - AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; - if (dataRequest != nil) { - NSError *spcError = nil; - NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; - // Request CKC to the server - NSString *licenseServer = (NSString *)[self->_drm objectForKey:@"licenseServer"]; - if (spcError != nil) { - [self finishLoadingWithError:spcError]; - self->_requestingCertificateErrored = YES; - } - if (spcData != nil) { - NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; - if(self.onGetLicense) { + if(self.onGetLicense) { + NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; + if (dataRequest != nil) { + NSError *spcError = nil; + NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; + // Request CKC to the server + NSString *licenseServer = (NSString *)[self->_drm objectForKey:@"licenseServer"]; + if (spcError != nil) { + [self finishLoadingWithError:spcError]; + self->_requestingCertificateErrored = YES; + } + if (spcData != nil) { + NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; self->_requestingCertificate = YES; self.onGetLicense(@{@"licenseUrl": licenseServer, @"contentId": contentId, @"spc": spcEncoded, @"target": self.reactTag}); - } else if(licenseServer != nil) { - - NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); - NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; - NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; - - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - [request setHTTPMethod:@"POST"]; - [request setURL:[NSURL URLWithString:licenseServer]]; - // HEADERS - NSDictionary *headers = (NSDictionary *)[self->_drm objectForKey:@"headers"]; - if (headers != nil) { - for (NSString *key in headers) { - NSString *value = headers[key]; - [request setValue:value forHTTPHeaderField:key]; + } else { + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorNoSPC + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining license.", + NSLocalizedFailureReasonErrorKey: @"No spc received.", + NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM config." + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; + } + } else { + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorNoDataRequest + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining DRM license.", + NSLocalizedFailureReasonErrorKey: @"No dataRequest found.", + NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM configuration." + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; + } + } else { + NSData *contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; + if (dataRequest != nil) { + NSError *spcError = nil; + NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; + // Request CKC to the server + NSString *licenseServer = (NSString *)[self->_drm objectForKey:@"licenseServer"]; + if (spcError != nil) { + [self finishLoadingWithError:spcError]; + self->_requestingCertificateErrored = YES; + } + if (spcData != nil) { + NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; + if(licenseServer != nil) { + + NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); + NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; + NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + [request setHTTPMethod:@"POST"]; + [request setURL:[NSURL URLWithString:licenseServer]]; + // HEADERS + NSDictionary *headers = (NSDictionary *)[self->_drm objectForKey:@"headers"]; + if (headers != nil) { + for (NSString *key in headers) { + NSString *value = headers[key]; + [request setValue:value forHTTPHeaderField:key]; + } } - } - - [request setHTTPBody: postData]; - NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; - NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; - if (error != nil) { - NSLog(@"Error getting license from %@, HTTP status code %li", url, (long)[httpResponse statusCode]); - [self finishLoadingWithError:error]; - self->_requestingCertificateErrored = YES; - } else { - if([httpResponse statusCode] != 200){ + + [request setHTTPBody: postData]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; + NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; + if (error != nil) { NSLog(@"Error getting license from %@, HTTP status code %li", url, (long)[httpResponse statusCode]); - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorLicenseRequestNotOk - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining license.", - NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"License server responded with status code %li", (long)[httpResponse statusCode]], - NSLocalizedRecoverySuggestionErrorKey: @"Did you send the correct data to the license Server? Is the server ok?" - } - ]; - [self finishLoadingWithError:licenseError]; + [self finishLoadingWithError:error]; self->_requestingCertificateErrored = YES; - } else if (data != nil) { - NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; - [dataRequest respondWithData:decodedData]; - [loadingRequest finishLoading]; } else { - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoDataFromLicenseRequest - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining DRM license.", - NSLocalizedFailureReasonErrorKey: @"No data received from the license server.", - NSLocalizedRecoverySuggestionErrorKey: @"Is the licenseServer ok?." - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; - } + if([httpResponse statusCode] != 200){ + NSLog(@"Error getting license from %@, HTTP status code %li", url, (long)[httpResponse statusCode]); + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorLicenseRequestNotOk + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining license.", + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"License server responded with status code %li", (long)[httpResponse statusCode]], + NSLocalizedRecoverySuggestionErrorKey: @"Did you send the correct data to the license Server? Is the server ok?" + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; + } else if (data != nil) { + NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + [dataRequest respondWithData:decodedData]; + [loadingRequest finishLoading]; + } else { + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorNoDataFromLicenseRequest + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining DRM license.", + NSLocalizedFailureReasonErrorKey: @"No data received from the license server.", + NSLocalizedRecoverySuggestionErrorKey: @"Is the licenseServer ok?." + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; + } - } - }]; - [postDataTask resume]; + } + }]; + [postDataTask resume]; + } + + } else { + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorNoSPC + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining license.", + NSLocalizedFailureReasonErrorKey: @"No spc received.", + NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM config." + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; } } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoSPC + code: RCTVideoErrorNoDataRequest userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining license.", - NSLocalizedFailureReasonErrorKey: @"No spc received.", - NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM config." + NSLocalizedDescriptionKey: @"Error obtaining DRM license.", + NSLocalizedFailureReasonErrorKey: @"No dataRequest found.", + NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM configuration." } - ]; + ]; [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } - - } else { - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoDataRequest - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining DRM license.", - NSLocalizedFailureReasonErrorKey: @"No dataRequest found.", - NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM configuration." - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; } } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" From 6d1b46fb301dd151d33f4d72cd67b6de69b34757 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Thu, 3 Dec 2020 20:37:57 +0900 Subject: [PATCH 07/11] fix --- ios/Video/RCTVideo.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 25e096c067..6f143bd9a0 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1784,6 +1784,7 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { if (certificateData != nil) { if(self.onGetLicense) { NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; + AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; if (dataRequest != nil) { NSError *spcError = nil; NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; From 1660ea3ea2f03bbbe398569f647627649f51d3e1 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Mon, 21 Dec 2020 20:17:44 +0900 Subject: [PATCH 08/11] Revert "fix" This reverts commit 6d1b46fb301dd151d33f4d72cd67b6de69b34757. --- ios/Video/RCTVideo.m | 1 - 1 file changed, 1 deletion(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 6f143bd9a0..25e096c067 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1784,7 +1784,6 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { if (certificateData != nil) { if(self.onGetLicense) { NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; - AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; if (dataRequest != nil) { NSError *spcError = nil; NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; From dc2608e1094881c55d91aeceaf79d6d7a3103908 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Mon, 21 Dec 2020 20:17:50 +0900 Subject: [PATCH 09/11] Revert "separate logic for getLicense js handling and native handling" This reverts commit 02884ee97ef69d0e010d870918abfd6c0114270e. --- ios/Video/RCTVideo.m | 210 ++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 124 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 25e096c067..7ec65fa09a 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1782,149 +1782,111 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { } if (certificateData != nil) { - if(self.onGetLicense) { - NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; - if (dataRequest != nil) { - NSError *spcError = nil; - NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; - // Request CKC to the server - NSString *licenseServer = (NSString *)[self->_drm objectForKey:@"licenseServer"]; - if (spcError != nil) { - [self finishLoadingWithError:spcError]; - self->_requestingCertificateErrored = YES; - } - if (spcData != nil) { - NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; + NSData *contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; + if (dataRequest != nil) { + NSError *spcError = nil; + NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; + // Request CKC to the server + NSString *licenseServer = (NSString *)[self->_drm objectForKey:@"licenseServer"]; + if (spcError != nil) { + [self finishLoadingWithError:spcError]; + self->_requestingCertificateErrored = YES; + } + if (spcData != nil) { + NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; + if(self.onGetLicense) { self->_requestingCertificate = YES; self.onGetLicense(@{@"licenseUrl": licenseServer, @"contentId": contentId, @"spc": spcEncoded, @"target": self.reactTag}); - } else { - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoSPC - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining license.", - NSLocalizedFailureReasonErrorKey: @"No spc received.", - NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM config." - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; - } - } else { - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoDataRequest - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining DRM license.", - NSLocalizedFailureReasonErrorKey: @"No dataRequest found.", - NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM configuration." - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; - } - } else { - NSData *contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; - AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; - if (dataRequest != nil) { - NSError *spcError = nil; - NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError]; - // Request CKC to the server - NSString *licenseServer = (NSString *)[self->_drm objectForKey:@"licenseServer"]; - if (spcError != nil) { - [self finishLoadingWithError:spcError]; - self->_requestingCertificateErrored = YES; - } - if (spcData != nil) { - NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; - if(licenseServer != nil) { - - NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); - NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; - NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; - - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - [request setHTTPMethod:@"POST"]; - [request setURL:[NSURL URLWithString:licenseServer]]; - // HEADERS - NSDictionary *headers = (NSDictionary *)[self->_drm objectForKey:@"headers"]; - if (headers != nil) { - for (NSString *key in headers) { - NSString *value = headers[key]; - [request setValue:value forHTTPHeaderField:key]; - } + } else if(licenseServer != nil) { + + NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); + NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; + NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + [request setHTTPMethod:@"POST"]; + [request setURL:[NSURL URLWithString:licenseServer]]; + // HEADERS + NSDictionary *headers = (NSDictionary *)[self->_drm objectForKey:@"headers"]; + if (headers != nil) { + for (NSString *key in headers) { + NSString *value = headers[key]; + [request setValue:value forHTTPHeaderField:key]; } - - [request setHTTPBody: postData]; - NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; - NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; - if (error != nil) { + } + + [request setHTTPBody: postData]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; + NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; + if (error != nil) { + NSLog(@"Error getting license from %@, HTTP status code %li", url, (long)[httpResponse statusCode]); + [self finishLoadingWithError:error]; + self->_requestingCertificateErrored = YES; + } else { + if([httpResponse statusCode] != 200){ NSLog(@"Error getting license from %@, HTTP status code %li", url, (long)[httpResponse statusCode]); - [self finishLoadingWithError:error]; + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorLicenseRequestNotOk + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining license.", + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"License server responded with status code %li", (long)[httpResponse statusCode]], + NSLocalizedRecoverySuggestionErrorKey: @"Did you send the correct data to the license Server? Is the server ok?" + } + ]; + [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; + } else if (data != nil) { + NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + [dataRequest respondWithData:decodedData]; + [loadingRequest finishLoading]; } else { - if([httpResponse statusCode] != 200){ - NSLog(@"Error getting license from %@, HTTP status code %li", url, (long)[httpResponse statusCode]); - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorLicenseRequestNotOk - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining license.", - NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"License server responded with status code %li", (long)[httpResponse statusCode]], - NSLocalizedRecoverySuggestionErrorKey: @"Did you send the correct data to the license Server? Is the server ok?" - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; - } else if (data != nil) { - NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; - [dataRequest respondWithData:decodedData]; - [loadingRequest finishLoading]; - } else { - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoDataFromLicenseRequest - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining DRM license.", - NSLocalizedFailureReasonErrorKey: @"No data received from the license server.", - NSLocalizedRecoverySuggestionErrorKey: @"Is the licenseServer ok?." - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; - } - + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorNoDataFromLicenseRequest + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining DRM license.", + NSLocalizedFailureReasonErrorKey: @"No data received from the license server.", + NSLocalizedRecoverySuggestionErrorKey: @"Is the licenseServer ok?." + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; } - }]; - [postDataTask resume]; - } - - } else { - NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoSPC - userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining license.", - NSLocalizedFailureReasonErrorKey: @"No spc received.", - NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM config." - } - ]; - [self finishLoadingWithError:licenseError]; - self->_requestingCertificateErrored = YES; + + } + }]; + [postDataTask resume]; } } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" - code: RCTVideoErrorNoDataRequest + code: RCTVideoErrorNoSPC userInfo: @{ - NSLocalizedDescriptionKey: @"Error obtaining DRM license.", - NSLocalizedFailureReasonErrorKey: @"No dataRequest found.", - NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM configuration." + NSLocalizedDescriptionKey: @"Error obtaining license.", + NSLocalizedFailureReasonErrorKey: @"No spc received.", + NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM config." } - ]; + ]; [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } + + } else { + NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" + code: RCTVideoErrorNoDataRequest + userInfo: @{ + NSLocalizedDescriptionKey: @"Error obtaining DRM license.", + NSLocalizedFailureReasonErrorKey: @"No dataRequest found.", + NSLocalizedRecoverySuggestionErrorKey: @"Check your DRM configuration." + } + ]; + [self finishLoadingWithError:licenseError]; + self->_requestingCertificateErrored = YES; } } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" From 954ebb899e011b9922e43aaa9452546dd9a91660 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Mon, 21 Dec 2020 20:19:49 +0900 Subject: [PATCH 10/11] cleanup --- ios/Video/RCTVideo.m | 47 ++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 7ec65fa09a..989167a6c0 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1764,11 +1764,15 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { } _loadingRequest = loadingRequest; NSURL *url = loadingRequest.request.URL; - NSString *contentId = [url.absoluteString stringByReplacingOccurrencesOfString:@"skd://" withString:@""]; if (self->_drm != nil) { + NSString *contentId; NSString *contentIdOverride = (NSString *)[self->_drm objectForKey:@"contentId"]; if (contentIdOverride != nil) { contentId = contentIdOverride; + } else if (self.onGetLicense) { + contentId = url.host; + } else { + contentId = [url.absoluteString stringByReplacingOccurrencesOfString:@"skd://" withString:@""]; } NSString *drmType = (NSString *)[self->_drm objectForKey:@"type"]; if ([drmType isEqualToString:@"fairplay"]) { @@ -1782,7 +1786,12 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { } if (certificateData != nil) { - NSData *contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + NSData *contentIdData; + if(self.onGetLicense) { + contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; + } else { + contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + } AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; if (dataRequest != nil) { NSError *spcError = nil; @@ -1794,19 +1803,18 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { self->_requestingCertificateErrored = YES; } if (spcData != nil) { - NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; if(self.onGetLicense) { + NSString *base64Encoded = [spcData base64EncodedStringWithOptions:0]; self->_requestingCertificate = YES; + if (licenseServer == nil) { + licenseServer = @""; + } self.onGetLicense(@{@"licenseUrl": licenseServer, @"contentId": contentId, - @"spc": spcEncoded, - @"target": self.reactTag}); + @"spcBase64": base64Encoded, + @"target": self.reactTag} + ); } else if(licenseServer != nil) { - - NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); - NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; - NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; [request setURL:[NSURL URLWithString:licenseServer]]; @@ -1818,8 +1826,17 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [request setValue:value forHTTPHeaderField:key]; } } + + if(self.onGetLicense) { + [request setHTTPBody: spcData]; + } else { + NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; + NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); + NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; + NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + [request setHTTPBody: postData]; + } - [request setHTTPBody: postData]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -1842,8 +1859,12 @@ - (BOOL)loadingRequestHandling:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } else if (data != nil) { - NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; - [dataRequest respondWithData:decodedData]; + if(self.onGetLicense) { + [dataRequest respondWithData:data]; + } else { + NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + [dataRequest respondWithData:decodedData]; + } [loadingRequest finishLoading]; } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" From 44b5915f671589caea0df71924b6cffc1858d10b Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Thu, 7 Jan 2021 15:22:22 +0900 Subject: [PATCH 11/11] fix --- Video.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Video.js b/Video.js index 0e6895c87d..b492d48b25 100644 --- a/Video.js +++ b/Video.js @@ -236,8 +236,8 @@ export default class Video extends Component { _onGetLicense = (event) => { if (this.props.drm && this.props.drm.getLicense instanceof Function) { const data = event.nativeEvent; - if (data && data.spc) { - const getLicenseOverride = this.props.drm.getLicense(data.spc, data.contentId, data.licenseUrl); + if (data && data.spcBase64) { + const getLicenseOverride = this.props.drm.getLicense(data.spcBase64, data.contentId, data.licenseUrl); const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not. getLicensePromise.then((result => { if (result !== undefined) {