CB-12882: (ios): adds support for permissions checks for captureVideo and captureImage methods
diff --git a/package.json b/package.json
index ea4a23b..6d45d64 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,9 @@
   "license": "Apache-2.0",
   "engines": {
     "cordovaDependencies": {
+      ">=1.4.4": {
+        "cordova-ios": ">=4.0.0"
+      },
       "2.0.0": {
         "cordova": ">100"
       }
diff --git a/src/ios/CDVCapture.h b/src/ios/CDVCapture.h
index 2cd8db8..c7433a4 100644
--- a/src/ios/CDVCapture.h
+++ b/src/ios/CDVCapture.h
@@ -28,6 +28,7 @@
     CAPTURE_APPLICATION_BUSY = 1,
     CAPTURE_INVALID_ARGUMENT = 2,
     CAPTURE_NO_MEDIA_FILES = 3,
+    CAPTURE_PERMISSION_DENIED = 4,
     CAPTURE_NOT_SUPPORTED = 20
 };
 typedef NSUInteger CDVCaptureError;
diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m
index 53e1b2b..7ab0832 100644
--- a/src/ios/CDVCapture.m
+++ b/src/ios/CDVCapture.m
@@ -58,17 +58,17 @@
 - (BOOL)prefersStatusBarHidden {
     return YES;
 }
-    
+
 - (UIViewController*)childViewControllerForStatusBarHidden {
     return nil;
 }
-    
+
 - (void)viewWillAppear:(BOOL)animated {
     SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
     if ([self respondsToSelector:sel]) {
         [self performSelector:sel withObject:nil afterDelay:0];
     }
-    
+
     [super viewWillAppear:animated];
 }
 
@@ -141,6 +141,7 @@
             pickerController = [[CDVImagePicker alloc] init];
         }
 
+        [self showAlertIfAccessProhibited];
         pickerController.delegate = self;
         pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
         pickerController.allowsEditing = NO;
@@ -247,6 +248,8 @@
         [self.commandDelegate sendPluginResult:result callbackId:callbackId];
         pickerController = nil;
     } else {
+        [self showAlertIfAccessProhibited];
+
         pickerController.delegate = self;
         pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
         pickerController.allowsEditing = NO;
@@ -292,6 +295,47 @@
     return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray];
 }
 
+- (void)showAlertIfAccessProhibited
+{
+    if (![self hasCameraAccess]) {
+        [self showPermissionsAlert];
+    }
+}
+
+- (BOOL)hasCameraAccess
+{
+    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+
+    return status != AVAuthorizationStatusDenied && status != AVAuthorizationStatusRestricted;
+}
+
+- (void)showPermissionsAlert
+{
+    __weak CDVCapture* weakSelf = self;
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [[[UIAlertView alloc] initWithTitle:[[NSBundle mainBundle]
+                                             objectForInfoDictionaryKey:@"CFBundleDisplayName"]
+                                    message:NSLocalizedString(@"Access to the camera has been prohibited; please enable it in the Settings app to continue.", nil)
+                                   delegate:weakSelf
+                          cancelButtonTitle:NSLocalizedString(@"OK", nil)
+                          otherButtonTitles:NSLocalizedString(@"Settings", nil), nil] show];
+    });
+}
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    if (buttonIndex == 1) {
+        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+    }
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_PERMISSION_DENIED];
+
+    [[pickerController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
+    [self.commandDelegate sendPluginResult:result callbackId:pickerController.callbackId];
+    pickerController = nil;
+    self.inUse = NO;
+}
+
 - (void)getMediaModes:(CDVInvokedUrlCommand*)command
 {
     // NSString* callbackId = [command argumentAtIndex:0];
@@ -337,7 +381,7 @@
         movieArray ? (NSObject*)                          movieArray:[NSNull null], @"video",
         audioArray ? (NSObject*)                          audioArray:[NSNull null], @"audio",
         nil];
-    
+
     NSData* jsonData = [NSJSONSerialization dataWithJSONObject:modes options:0 error:nil];
     NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
 
@@ -608,7 +652,7 @@
 	if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
         self.edgesForExtendedLayout = UIRectEdgeNone;
     }
-    
+
     // create view and display
     CGRect viewRect = [[UIScreen mainScreen] applicationFrame];
     UIView* tmp = [[UIView alloc] initWithFrame:viewRect];
@@ -737,7 +781,7 @@
 {
     UIInterfaceOrientationMask orientation = UIInterfaceOrientationMaskPortrait;
     UIInterfaceOrientationMask supported = [captureCommand.viewController supportedInterfaceOrientations];
-    
+
     orientation = orientation | (supported & UIInterfaceOrientationMaskPortraitUpsideDown);
     return orientation;
 }
@@ -746,7 +790,7 @@
 {
     NSUInteger orientation = UIInterfaceOrientationMaskPortrait; // must support portrait
     NSUInteger supported = [captureCommand.viewController supportedInterfaceOrientations];
-    
+
     orientation = orientation | (supported & UIInterfaceOrientationMaskPortraitUpsideDown);
     return orientation;
 }
@@ -773,7 +817,7 @@
         __block NSError* error = nil;
 
         __weak CDVAudioRecorderViewController* weakSelf = self;
-        
+
         void (^startRecording)(void) = ^{
             [weakSelf.avSession setCategory:AVAudioSessionCategoryRecord error:&error];
             [weakSelf.avSession setActive:YES error:&error];
@@ -794,7 +838,7 @@
             }
             UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
         };
-        
+
         SEL rrpSel = NSSelectorFromString(@"requestRecordPermission:");
         if ([self.avSession respondsToSelector:rrpSel])
         {
diff --git a/tests/tests.js b/tests/tests.js
index fd2f60b..9434fc1 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -243,6 +243,28 @@
         navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);
     }
 
+    function permissionWasNotAllowed() {
+        log('Media has been captured. Have you forgotten to disallow camera for this app?');
+    }
+
+    function catchPermissionError(error) {
+        if (CaptureError.CAPTURE_PERMISSION_DENIED === error.code) {
+            log('Sucess: permission error has been detected!');
+        } else {
+            log('Error: another error with code: ' + error.code);
+        }
+    }
+
+    function getVideoPermissionError() {
+        var options = { limit: 1, duration: 10 };
+        navigator.device.capture.captureVideo(permissionWasNotAllowed, catchPermissionError, options);
+    }
+
+    function getImagePermissionError() {
+        var options = { limit: 1 };
+        navigator.device.capture.captureImage(permissionWasNotAllowed, catchPermissionError, options);
+    }
+
     function resolveMediaFileURL(mediaFile, callback) {
         resolveLocalFileSystemURL(mediaFile.localURL, function (entry) {
             log("Resolved by URL: " + mediaFile.localURL);
@@ -300,7 +322,11 @@
         '<p/> <div id="video"></div>' +
         'Expected result: Record 10 second video. Status box will update with video file that you can play.' +
         '<p/> <div id="video_and_resolve"></div>' +
-        'Expected result: Record 5 second video. Status box will show that URL was resolved and video will get added at the bottom of the status box for playback.';
+        'Expected result: Record 5 second video. Status box will show that URL was resolved and video will get added at the bottom of the status box for playback.' +
+        '<p/> <div id="prohibited_camera_video"></div>' +
+        'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app' +
+        '<p/> <div id="prohibited_camera_image"></div>' +
+        'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app';
 
     createActionButton('Capture 10 sec of audio and play', function () {
         getAudio();
@@ -321,4 +347,12 @@
     createActionButton('Capture 5 sec of video and resolve', function () {
         resolveVideo();
     }, 'video_and_resolve');
+
+    createActionButton('Disable access to Camera and click to capture video', function() {
+      getVideoPermissionError();
+    }, 'prohibited_camera_video');
+
+    createActionButton('Disable access to Camera and click to capture image', function() {
+      getImagePermissionError();
+    }, 'prohibited_camera_image');
 };