Release 9.0.0.16887
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.PackageManager / Tizen.Applications / Package.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.Threading.Tasks;
21
22 namespace Tizen.Applications
23 {
24     /// <summary>
25     /// This class provides the methods and properties to get information about the packages.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class Package
29     {
30         private const string LogTag = "Tizen.Applications";
31
32         private string _id = string.Empty;
33         private string _mainAppId = string.Empty;
34         private string _label = string.Empty;
35         private string _iconPath = string.Empty;
36         private string _version = string.Empty;
37         private PackageType _type;
38         private Interop.PackageManager.StorageType _installedStorageType;
39         private string _rootPath = string.Empty;
40         private string _expansionPackageName = string.Empty;
41         private bool _isSystemPackage;
42         private bool _isRemovable;
43         private bool _isPreloaded;
44         private bool _isAccessible;
45         private IReadOnlyDictionary<CertificateType, PackageCertificate> _certificates;
46         private List<string> _privileges;
47         private int _installedTime;
48
49         private Dictionary<IntPtr, Interop.PackageManager.PackageManagerSizeInfoCallback> _packageManagerSizeInfoCallbackDict = new Dictionary<IntPtr, Interop.PackageManager.PackageManagerSizeInfoCallback>();
50         private int _callbackId = 0;
51         private List<PackageDependencyInformation> _dependencyTo;
52         private List<PackageDependencyInformation> _dependencyFrom;
53         private IReadOnlyDictionary<string, IEnumerable<string>> _allowedPackagesAndPrivilegesList;
54
55         private Package(string pkgId)
56         {
57             _id = pkgId;
58         }
59
60         /// <summary>
61         /// The package ID.
62         /// </summary>
63         /// <since_tizen> 3 </since_tizen>
64         public string Id { get { return _id; } }
65
66         /// <summary>
67         /// Label of the package.
68         /// </summary>
69         /// <since_tizen> 3 </since_tizen>
70         public string Label { get { return _label; } }
71
72         /// <summary>
73         /// Absolute path to the icon image.
74         /// </summary>
75         /// <since_tizen> 3 </since_tizen>
76         public string IconPath { get { return _iconPath; } }
77
78         /// <summary>
79         /// Version of the package.
80         /// </summary>
81         /// <since_tizen> 3 </since_tizen>
82         public string Version { get { return _version; } }
83
84         /// <summary>
85         /// Type of the package.
86         /// </summary>
87         /// <since_tizen> 3 </since_tizen>
88         public PackageType PackageType { get { return _type; } }
89
90         /// <summary>
91         /// Installed storage type for the package.
92         /// </summary>
93         /// <since_tizen> 3 </since_tizen>
94         public StorageType InstalledStorageType { get { return (StorageType)_installedStorageType; } }
95
96         /// <summary>
97         /// Root path for the package.
98         /// </summary>
99         /// <since_tizen> 3 </since_tizen>
100         public string RootPath { get { return _rootPath; } }
101
102         /// <summary>
103         /// Expansion package name for the package.
104         /// </summary>
105         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
106         /// <privlevel>platform</privlevel>
107         /// <since_tizen> 3 </since_tizen>
108         public string TizenExpansionPackageName { get { return _expansionPackageName; } }
109
110         /// <summary>
111         /// Checks whether the package is a system package.
112         /// </summary>
113         /// <since_tizen> 3 </since_tizen>
114         public bool IsSystemPackage { get { return _isSystemPackage; } }
115
116         /// <summary>
117         /// Checks whether the package is removable.
118         /// </summary>
119         /// <since_tizen> 3 </since_tizen>
120         public bool IsRemovable { get { return _isRemovable; } }
121
122         /// <summary>
123         /// Checks whether the package is preloaded.
124         /// </summary>
125         /// <since_tizen> 3 </since_tizen>
126         public bool IsPreloaded { get { return _isPreloaded; } }
127
128         /// <summary>
129         /// Checks whether the current package is accessible.
130         /// </summary>
131         /// <since_tizen> 3 </since_tizen>
132         public bool IsAccessible { get { return _isAccessible; } }
133
134         /// <summary>
135         /// Certificate information for the package.
136         /// </summary>
137         /// <since_tizen> 3 </since_tizen>
138         public IReadOnlyDictionary<CertificateType, PackageCertificate> Certificates { get { return _certificates; } }
139
140         /// <summary>
141         /// Requested privilege for the package.
142         /// </summary>
143         /// <since_tizen> 3 </since_tizen>
144         public IEnumerable<string> Privileges { get { return _privileges; } }
145
146         /// <summary>
147         /// Installed time of the package.
148         /// </summary>
149         /// <since_tizen> 3 </since_tizen>
150         public int InstalledTime { get { return _installedTime; } }
151
152         /// <summary>
153         /// Main application info of the package.
154         /// </summary>
155         /// <since_tizen> 6 </since_tizen>
156         public ApplicationInfo MainApplication
157         {
158             get
159             {
160                 ApplicationInfo applicaionInfo = new ApplicationInfo(_mainAppId);
161                 return applicaionInfo;
162             }
163         }
164
165         /// <summary>
166         /// Retrieves all the application IDs of this package.
167         /// </summary>
168         /// <returns>Returns a dictionary containing all the application information for a given application type.</returns>
169         /// <since_tizen> 3 </since_tizen>
170         public IEnumerable<ApplicationInfo> GetApplications()
171         {
172             return GetApplications(ApplicationType.All);
173         }
174
175         /// <summary>
176         /// Retrieves all the application IDs of this package.
177         /// </summary>
178         /// <param name="type">Optional: AppType enumeration value.</param>
179         /// <returns>Returns a dictionary containing all the application information for a given application type.</returns>
180         /// <since_tizen> 3 </since_tizen>
181         public IEnumerable<ApplicationInfo> GetApplications(ApplicationType type)
182         {
183             List<ApplicationInfo> appInfoList = new List<ApplicationInfo>();
184             Interop.Package.PackageInfoAppInfoCallback cb = (Interop.Package.AppType appType, string appId, IntPtr userData) =>
185             {
186                 appInfoList.Add(new ApplicationInfo(appId));
187                 return true;
188             };
189
190             IntPtr packageInfoHandle;
191             Interop.PackageManager.ErrorCode err = Interop.Package.PackageInfoCreate(Id, out packageInfoHandle);
192             if (err != Interop.PackageManager.ErrorCode.None)
193             {
194                 Log.Warn(LogTag, string.Format("Failed to create native handle for package info of {0}. err = {1}", Id, err));
195             }
196
197             err = Interop.Package.PackageInfoForeachAppInfo(packageInfoHandle, (Interop.Package.AppType)type, cb, IntPtr.Zero);
198             if (err != Interop.PackageManager.ErrorCode.None)
199             {
200                 Log.Warn(LogTag, string.Format("Failed to application info of {0}. err = {1}", Id, err));
201             }
202
203             err = Interop.Package.PackageInfoDestroy(packageInfoHandle);
204             if (err != Interop.PackageManager.ErrorCode.None)
205             {
206                 Log.Warn(LogTag, string.Format("Failed to destroy native handle for package info of {0}. err = {1}", Id, err));
207             }
208             return appInfoList;
209         }
210
211         /// <summary>
212         /// Retrieves all the application IDs of this package.
213         /// </summary>
214         /// <param name="componentType">Optional: AppType enumeration value.</param>
215         /// <returns>Returns a dictionary containing all the application information for a given application type.</returns>
216         /// <since_tizen> 6 </since_tizen>
217         public IEnumerable<ApplicationInfo> GetApplications(ApplicationComponentType componentType)
218         {
219             return GetApplications(ToApplicationType(componentType));
220         }
221
222         /// <summary>
223         /// Packages required by this package
224         /// </summary>
225         /// <since_tizen> 6 </since_tizen>
226         public IEnumerable<PackageDependencyInformation> DependencyTo { get { return _dependencyTo; } }
227
228         /// <summary>
229         /// Packages that require this package
230         /// </summary>
231         /// <since_tizen> 6 </since_tizen>
232         public IEnumerable<PackageDependencyInformation> DependencyFrom { get { return _dependencyFrom; } }
233
234         /// <summary>
235         /// Gets the package size information.
236         /// </summary>
237         /// <returns>Package size information.</returns>
238         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
239         /// <since_tizen> 3 </since_tizen>
240         public async Task<PackageSizeInformation> GetSizeInformationAsync()
241         {
242             TaskCompletionSource<PackageSizeInformation> tcs = new TaskCompletionSource<PackageSizeInformation>();
243             Interop.PackageManager.PackageManagerSizeInfoCallback sizeInfoCb = (pkgId, sizeInfoHandle, userData) =>
244             {
245                 if (sizeInfoHandle != IntPtr.Zero && Id == pkgId)
246                 {
247                     var pkgSizeInfo = PackageSizeInformation.GetPackageSizeInformation(sizeInfoHandle);
248                     tcs.TrySetResult(pkgSizeInfo);
249                 }
250
251                 lock (_packageManagerSizeInfoCallbackDict)
252                 {
253                     _packageManagerSizeInfoCallbackDict.Remove(userData);
254                 }
255             };
256
257             IntPtr callbackId;
258             lock (_packageManagerSizeInfoCallbackDict)
259             {
260                 callbackId = (IntPtr)_callbackId++;
261                 _packageManagerSizeInfoCallbackDict[callbackId] = sizeInfoCb;
262             }
263
264             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerGetSizeInfo(Id, sizeInfoCb, callbackId);
265             if (err != Interop.PackageManager.ErrorCode.None)
266             {
267                 tcs.TrySetException(PackageManagerErrorFactory.GetException(err, "Failed to get total package size info of " + Id));
268             }
269             return await tcs.Task.ConfigureAwait(false);
270         }
271
272         /// <summary>
273         /// Compares the certificate information with the given package ID.
274         /// </summary>
275         /// <param name="packageId">ID of the package.</param>
276         /// <returns>Certificate comparison result.</returns>
277         /// <exception cref="ArgumentException">Thrown when a failed input package ID is invalid.</exception>
278         /// <exception cref="System.IO.IOException">Thrown when the method failed due to an internal I/O error.</exception>
279         /// <since_tizen> 3 </since_tizen>
280         public CertCompareResultType CompareCertInfo(string packageId)
281         {
282             Interop.PackageManager.CertCompareResultType compareResult;
283             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerCompareCertInfo(Id, packageId, out compareResult);
284             if (err != Interop.PackageManager.ErrorCode.None)
285             {
286                 throw PackageManagerErrorFactory.GetException(err, "Failed to compare package cert info");
287             }
288
289             return (CertCompareResultType)compareResult;
290         }
291
292         /// <summary>
293         /// The allowed packages and required privileges information.
294         /// </summary>
295         /// <remarks> The dictionary contains application IDs as the keys, and a collection of privileges related to that application as the value.</remarks>
296         /// <since_tizen> 9 </since_tizen>
297         public IReadOnlyDictionary<string, IEnumerable<string>> AllowedPackagesAndPrivileges
298         {
299             get { return _allowedPackagesAndPrivilegesList; }
300         }
301
302         // This method assumes that given arguments are already validated and have valid values.
303         internal static Package CreatePackage(IntPtr handle, string pkgId)
304         {
305             Package package = new Package(pkgId);
306
307             var err = Interop.PackageManager.ErrorCode.None;
308             err = Interop.Package.PackageInfoGetMainAppId(handle, out package._mainAppId);
309             if (err != Interop.PackageManager.ErrorCode.None)
310             {
311                 Log.Warn(LogTag, "Failed to get package main app id of " + pkgId);
312             }
313             err = Interop.Package.PackageInfoGetLabel(handle, out package._label);
314             if (err != Interop.PackageManager.ErrorCode.None)
315             {
316                 Log.Warn(LogTag, "Failed to get package label of " + pkgId);
317             }
318             err = Interop.Package.PackageInfoGetIconPath(handle, out package._iconPath);
319             if (err != Interop.PackageManager.ErrorCode.None)
320             {
321                 Log.Warn(LogTag, "Failed to get package icon path of " + pkgId);
322             }
323             err = Interop.Package.PackageInfoGetVersion(handle, out package._version);
324             if (err != Interop.PackageManager.ErrorCode.None)
325             {
326                 Log.Warn(LogTag, "Failed to get package version of " + pkgId);
327             }
328
329             string type;
330             Interop.Package.PackageInfoGetType(handle, out type);
331             if (Enum.TryParse(type, true, out package._type) == false)
332             {
333                 Log.Warn(LogTag, "Failed to get package type of " + pkgId);
334             }
335             err = Interop.Package.PackageInfoGetRootPath(handle, out package._rootPath);
336             if (err != Interop.PackageManager.ErrorCode.None)
337             {
338                 Log.Warn(LogTag, "Failed to get package root directory of " + pkgId);
339             }
340             err = Interop.Package.PackageInfoGetTepName(handle, out package._expansionPackageName);
341             if (err != Interop.PackageManager.ErrorCode.None)
342             {
343                 Log.Warn(LogTag, "Failed to get expansion package name of " + pkgId);
344                 package._expansionPackageName = string.Empty;
345             }
346
347             err = Interop.Package.PackageInfoGetInstalledStorage(handle, out package._installedStorageType);
348             if (err != Interop.PackageManager.ErrorCode.None)
349             {
350                 Log.Warn(LogTag, "Failed to get installed storage type of " + pkgId);
351             }
352             Interop.Package.PackageInfoIsSystemPackage(handle, out package._isSystemPackage);
353             if (err != Interop.PackageManager.ErrorCode.None)
354             {
355                 Log.Warn(LogTag, "Failed to get whether package " + pkgId + " is system package or not");
356             }
357             Interop.Package.PackageInfoIsRemovablePackage(handle, out package._isRemovable);
358             if (err != Interop.PackageManager.ErrorCode.None)
359             {
360                 Log.Warn(LogTag, "Failed to get whether package " + pkgId + " is removable or not");
361             }
362             Interop.Package.PackageInfoIsPreloadPackage(handle, out package._isPreloaded);
363             if (err != Interop.PackageManager.ErrorCode.None)
364             {
365                 Log.Warn(LogTag, "Failed to get whether package " + pkgId + " is preloaded or not");
366             }
367             Interop.Package.PackageInfoIsAccessible(handle, out package._isAccessible);
368             if (err != Interop.PackageManager.ErrorCode.None)
369             {
370                 Log.Warn(LogTag, "Failed to get whether package " + pkgId + " is accessible or not");
371             }
372             try
373             {
374                 Interop.Package.PackageInfoGetInstalledTime(handle, out package._installedTime);
375                 if (err != Interop.PackageManager.ErrorCode.None)
376                 {
377                     Log.Warn(LogTag, "Failed to get installed time of " + pkgId);
378                 }
379             }
380             catch (TypeLoadException)
381             {
382                 // To support in API vesion 3.0
383                 package._installedTime = 0;
384             }
385
386             package._certificates = PackageCertificate.GetPackageCertificates(handle);
387             package._privileges = GetPackagePrivilegeInformation(handle);
388             package._dependencyTo = GetPackageDependency(handle);
389             package._dependencyFrom = GetPackageDependencyDependsOn(handle);
390             package._allowedPackagesAndPrivilegesList = GetAllowedPackagesAndPrivileges(handle);
391             return package;
392         }
393
394         internal static Package GetPackage(string packageId)
395         {
396             IntPtr packageInfoHandle;
397             Interop.PackageManager.ErrorCode err = Interop.Package.PackageInfoCreate(packageId, out packageInfoHandle);
398             if (err != Interop.PackageManager.ErrorCode.None)
399             {
400                 throw PackageManagerErrorFactory.GetException(err, string.Format("Failed to create native handle for package info of {0}", packageId));
401             }
402
403             Package package = CreatePackage(packageInfoHandle, packageId);
404
405             err = Interop.Package.PackageInfoDestroy(packageInfoHandle);
406             if (err != Interop.PackageManager.ErrorCode.None)
407             {
408                 Log.Warn(LogTag, string.Format("Failed to destroy native handle for package info of {0}. err = {1}", packageId, err));
409             }
410             return package;
411         }
412
413         internal static Package GetPackage(IntPtr packageInfoHandle)
414         {
415             String packageId;
416             Interop.PackageManager.ErrorCode err = Interop.Package.PackageInfoGetPackage(packageInfoHandle, out packageId);
417             if (err != Interop.PackageManager.ErrorCode.None)
418             {
419                 throw PackageManagerErrorFactory.GetException(err, "Failed to get package id for given package handle.");
420             }
421             return CreatePackage(packageInfoHandle, packageId);
422         }
423
424         private static List<string> GetPackagePrivilegeInformation(IntPtr packageInfoHandle)
425         {
426             List<string> privileges = new List<string>();
427             Interop.Package.PackageInfoPrivilegeInfoCallback privilegeInfoCb = (privilege, userData) =>
428             {
429                 privileges.Add(privilege);
430                 return true;
431             };
432
433             Interop.PackageManager.ErrorCode err = Interop.Package.PackageInfoForeachPrivilegeInfo(packageInfoHandle, privilegeInfoCb, IntPtr.Zero);
434             if (err != Interop.PackageManager.ErrorCode.None)
435             {
436                 Log.Warn(LogTag, string.Format("Failed to get privilage info. err = {0}", err));
437             }
438             return privileges;
439         }
440
441         private ApplicationType ToApplicationType(ApplicationComponentType componentType)
442         {
443             ApplicationType applicationType = 0;
444             if (componentType == Tizen.Applications.ApplicationComponentType.UIApplication)
445                 applicationType = Tizen.Applications.ApplicationType.Ui;
446             else if (componentType == Tizen.Applications.ApplicationComponentType.ServiceApplication)
447                 applicationType = Tizen.Applications.ApplicationType.Service;
448             else if (componentType == Tizen.Applications.ApplicationComponentType.WidgetApplication)
449                 applicationType = Tizen.Applications.ApplicationType.Widget;
450             else if (componentType == Tizen.Applications.ApplicationComponentType.WatchApplication)
451                 applicationType = Tizen.Applications.ApplicationType.Watch;
452
453             return applicationType;
454         }
455
456         private static List<PackageDependencyInformation> GetPackageDependency(IntPtr packageInfoHandle)
457         {
458             List<PackageDependencyInformation> dependencies = new List<PackageDependencyInformation>();
459             Interop.Package.PackageInfoDependencyInfoCallback dependencyInfoCb = (from, to, type, requiredVersion, userData) =>
460             {
461                 dependencies.Add(PackageDependencyInformation.GetPackageDependencyInformation(from, to, type, requiredVersion));
462                 return true;
463             };
464
465             Interop.PackageManager.ErrorCode err = Interop.Package.PackageInfoForeachDependencyInfo(packageInfoHandle, dependencyInfoCb, IntPtr.Zero);
466             if (err != Interop.PackageManager.ErrorCode.None)
467             {
468                 Log.Warn(LogTag, string.Format("Failed to get dependency info. err = {0}", err));
469             }
470             return dependencies;
471         }
472
473         private static List<PackageDependencyInformation> GetPackageDependencyDependsOn(IntPtr packageInfoHandle)
474         {
475             List<PackageDependencyInformation> dependencies = new List<PackageDependencyInformation>();
476             Interop.Package.PackageInfoDependencyInfoCallback dependencyInfoCb = (from, to, type, requiredVersion, userData) =>
477             {
478                 dependencies.Add(PackageDependencyInformation.GetPackageDependencyInformation(from, to, type, requiredVersion));
479                 return true;
480             };
481
482             Interop.PackageManager.ErrorCode err = Interop.Package.PackageInfoForeachDependencyInfoDependsOn(packageInfoHandle, dependencyInfoCb, IntPtr.Zero);
483             if (err != Interop.PackageManager.ErrorCode.None)
484             {
485                 Log.Warn(LogTag, string.Format("Failed to get dependency info. err = {0}", err));
486             }
487             return dependencies;
488         }
489
490         private static Dictionary<string, IEnumerable<string>> GetAllowedPackagesAndPrivileges(IntPtr packageInfoHandle)
491         {
492             Interop.PackageManager.ErrorCode err;
493             Dictionary<string, IEnumerable<string>> allowedPackagesAndPrivileges = new Dictionary<string, IEnumerable<string>>();
494             Interop.Package.PackageInfoResAllowedPackageCallback allowedPackageCallback = (allowedPackage, requiredPrivileges, userData) =>
495             {
496                 List<string> requiredPrivilegesList = new List<string>();
497                 Interop.Package.PackageInfoPrivilegeInfoCallback requiredPrivCallback = (priv, requiredPrivCbUserData) =>
498                 {
499                     requiredPrivilegesList.Add(priv);
500                     return true;
501                 };
502                 err = Interop.Package.PackageInfoForeachRequiredPrivilege(requiredPrivileges, requiredPrivCallback, IntPtr.Zero);
503                 if (err != Interop.PackageManager.ErrorCode.None)
504                 {
505                     Log.Warn(LogTag, string.Format("Failed to get required privileges of allowed packages info. err = {0}", err));
506                 }
507                 else
508                 {
509                     allowedPackagesAndPrivileges.Add(allowedPackage, requiredPrivilegesList);
510                 }
511                 return true;
512             };
513
514             err = Interop.Package.PackageInfoForeachResAllowedPackage(packageInfoHandle, allowedPackageCallback, IntPtr.Zero);
515             if (err != Interop.PackageManager.ErrorCode.None)
516             {
517                 Log.Warn(LogTag, string.Format("Failed to get allowed packages info. err = {0}", err));
518             }
519             return allowedPackagesAndPrivileges;
520         }
521     }
522 }