[Security] Fix PrivacyPrivilegeManager.RequestPermissions crash issue (#1651)
authorSeungkeun Lee <sngn.lee@samsung.com>
Tue, 9 Jun 2020 08:36:07 +0000 (17:36 +0900)
committerGitHub <noreply@github.com>
Tue, 9 Jun 2020 08:36:07 +0000 (17:36 +0900)
src/Tizen.Security.PrivacyPrivilegeManager/Tizen.Security/PrivacyPrivilegeManager.cs

index 83de89a..9c47cd3 100644 (file)
@@ -18,7 +18,6 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
-using Tizen.Internals.Errors;
 
 namespace Tizen.Security
 {
@@ -29,6 +28,8 @@ namespace Tizen.Security
     public static class PrivacyPrivilegeManager
     {
         private const string LogTag = "Tizen.Privilege";
+        private static Dictionary<int, TaskCompletionSource<RequestMultipleResponseEventArgs>> s_multipleRequestMap = new Dictionary<int, TaskCompletionSource<RequestMultipleResponseEventArgs>>();
+        private static int s_requestId = 0;
         private static IDictionary<string, WeakReference<ResponseContext>> s_responseWeakMap = new Dictionary<string, WeakReference<ResponseContext>>();
         private static Interop.PrivacyPrivilegeManager.RequestResponseCallback s_requestResponseCb =
                        (Interop.PrivacyPrivilegeManager.CallCause cause, Interop.PrivacyPrivilegeManager.RequestResult result,
@@ -62,6 +63,7 @@ namespace Tizen.Security
 
         private static IDictionary<string, ResponseContext> s_responseMap = new Dictionary<string, ResponseContext>();
         private static HashSet<string> s_PrivilegesInProgress = new HashSet<string>();
+        private static Interop.PrivacyPrivilegeManager.RequestMultipleResponseCallback s_multipleCallback = MultipleRequestHandler;
 
         private static string[] CheckPrivilegesArgument(IEnumerable<string> privileges, string methodName)
         {
@@ -276,32 +278,14 @@ namespace Tizen.Security
 
             Log.Info(LogTag, "Sending request for permissions: " + string.Join(" ", privilegesArray));
 
+            int requestId = 0;
+            lock (s_multipleRequestMap)
+            {
+                requestId = s_requestId++;
+            }
             TaskCompletionSource<RequestMultipleResponseEventArgs> permissionResponsesTask = new TaskCompletionSource<RequestMultipleResponseEventArgs>();
-            int ret = (int)Interop.PrivacyPrivilegeManager.RequestPermissions(privilegesArray, (uint)privilegesArray.Length,
-                        (Interop.PrivacyPrivilegeManager.CallCause cause, Interop.PrivacyPrivilegeManager.RequestResult[] results,
-                        string[] requestedPrivileges, uint privilegesCount, IntPtr userData) =>
-                        {
-                            Log.Info(LogTag, "Sending request for permissions: ");
-                            RequestMultipleResponseEventArgs requestResponse = new RequestMultipleResponseEventArgs();
-                            PermissionRequestResponse[] permissionResponses = new PermissionRequestResponse[privilegesCount];
-
-                            for (int iterator = 0; iterator < privilegesCount; ++iterator)
-                            {
-                                permissionResponses[iterator] = new PermissionRequestResponse
-                                {
-                                    Privilege = requestedPrivileges[iterator],
-                                    Result = (RequestResult)results[iterator]
-                                };
-                            }
-                            requestResponse.Cause = (CallCause)cause;
-                            requestResponse.Responses = permissionResponses;
-
-                            foreach (string privilege in requestedPrivileges)
-                            {
-                                s_PrivilegesInProgress.Remove(privilege);
-                            }
-                            permissionResponsesTask.SetResult(requestResponse);
-                        }, IntPtr.Zero);
+            s_multipleRequestMap[requestId] = permissionResponsesTask;
+            int ret = (int)Interop.PrivacyPrivilegeManager.RequestPermissions(privilegesArray, (uint)privilegesArray.Length, s_multipleCallback, (IntPtr)requestId);
 
             if (ret != (int)Interop.PrivacyPrivilegeManager.ErrorCode.None)
             {
@@ -310,6 +294,7 @@ namespace Tizen.Security
                 {
                     s_PrivilegesInProgress.Remove(privilege);
                 }
+                s_multipleRequestMap.Remove(requestId);
                 throw PrivacyPrivilegeManagerErrorFactory.GetException(ret);
             }
             else
@@ -380,6 +365,38 @@ namespace Tizen.Security
             return s_responseWeakMap[privilege];
         }
 
+        private static void MultipleRequestHandler(Interop.PrivacyPrivilegeManager.CallCause cause, Interop.PrivacyPrivilegeManager.RequestResult[] results,
+            string[] requestedPrivileges, uint privilegesCount, IntPtr userData)
+        {
+            int requestId = (int)userData;
+            if (!s_multipleRequestMap.ContainsKey(requestId))
+            {
+                return;
+            }
+
+            var tcs = s_multipleRequestMap[requestId];
+            RequestMultipleResponseEventArgs requestResponse = new RequestMultipleResponseEventArgs();
+            PermissionRequestResponse[] permissionResponses = new PermissionRequestResponse[privilegesCount];
+
+            for (int iterator = 0; iterator < privilegesCount; ++iterator)
+            {
+                permissionResponses[iterator] = new PermissionRequestResponse
+                {
+                    Privilege = requestedPrivileges[iterator],
+                    Result = (RequestResult)results[iterator]
+                };
+            }
+            requestResponse.Cause = (CallCause)cause;
+            requestResponse.Responses = permissionResponses;
+
+            foreach (string privilege in requestedPrivileges)
+            {
+                s_PrivilegesInProgress.Remove(privilege);
+            }
+            tcs.SetResult(requestResponse);
+            s_multipleRequestMap.Remove(requestId);
+        }
+
         /// <summary>
         /// This class manages event handlers of the privilege permission requests.
         /// This class enables having event handlers for an individual privilege.