added initialization for subscribe handle
[platform/core/csapi/tizenfx.git] / src / Tizen.Account.AccountManager / Tizen.Account.AccountManager / AccountService.cs
1 /*
2  * Copyright (c) 2016 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
20 namespace Tizen.Account.AccountManager
21 {
22     /// <summary>
23     /// The AccountManager APIs is separated into two major sections:
24     /// 1. Registering an account provider while an application is installed. This information will be used for the Add account screen.
25     /// 2. Adding an account information when an application signs in successfully to share the account information to the Tizen system. This information will be shown in the Tizen settings account menu.
26     ///
27     /// The APIs of both of the sections consist of the following functionality:
28     /// <list>
29     /// <item> Create an account or account provider </item>
30     /// <item> Update an account or account provider(Only available for the creator) </item>
31     /// <item> Delete an account or account provider(Only available for the creator) </item>
32     /// <item> Read an account or account provider with some filter </item>
33     /// </list>
34     /// </summary>
35
36     public static class AccountService
37     {
38         /// <summary>
39         /// This is contact capability string.
40         /// </summary>
41         public static readonly string ContactCapability = "http://tizen.org/account/capability/contact";
42
43         /// <summary>
44         /// This is calendar capability string.
45         /// </summary>
46         public static readonly string CalendarCapability = "http://tizen.org/account/capability/calendar";
47
48         /// <summary>
49         /// This is email capability string.
50         /// </summary>
51         public static readonly string EmailCapability = "http://tizen.org/account/capability/email";
52
53         /// <summary>
54         /// This is photo capability string.
55         /// </summary>
56         public static readonly string PhotoCapability = "http://tizen.org/account/capability/photo";
57
58         /// <summary>
59         /// This is video capability string.
60         /// </summary>
61         public static readonly string VideoCapability = "http://tizen.org/account/capability/video";
62
63         /// <summary>
64         /// This is music capability string.
65         /// </summary>
66         public static readonly string MusicCapability = "http://tizen.org/account/capability/music";
67
68         /// <summary>
69         /// This is document capability string.
70         /// </summary>
71         public static readonly string DocumentCapability = "http://tizen.org/account/capability/document";
72
73         /// <summary>
74         /// This is message capability string.
75         /// </summary>
76         public static readonly string MessageCapability = "http://tizen.org/account/capability/message";
77
78         /// <summary>
79         /// This is game capability string.
80         /// </summary>
81         public static readonly string GameCapability = "http://tizen.org/account/capability/game";
82
83         /// <summary>
84         /// Retrieves all accounts details from the account database.
85         /// </summary>
86         /// <returns>List of Accounts</returns>
87         /// <privilege>http://tizen.org/privilege/account.read</privilege>
88         /// <exception cref="InvalidOperationException">In case of any DB error. </exception>
89         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
90         public static IEnumerable<Account> GetAccountsAsync()
91         {
92             List<Account> accounts = new List<Account>();
93             List<int> values = new List<int>();
94             Interop.Account.AccountCallback accountCallback = (IntPtr data, IntPtr userdata) =>
95             {
96                 Account account = new Account(data);
97                 values.Add(account.AccountId);
98                 account.Dispose();
99                 return true;
100             };
101
102             AccountError res = (AccountError)Interop.AccountService.AccountForeachAccountFromDb(accountCallback, IntPtr.Zero);
103             if (res != AccountError.None)
104             {
105                 throw AccountErrorFactory.CreateException(res, "Failed to AccountForeachAccountFromDb");
106             }
107
108             foreach (int i in values)
109             {
110                 Account account = AccountService.GetAccountById(i);
111                 accounts.Add(account);
112             }
113
114             return accounts;
115         }
116
117         /// <summary>
118         /// Retrieve an account with the account ID.
119         /// </summary>
120         /// <param name="accountId"> The account Id to be searched.</param>
121         /// <returns>Account instance with reference to the given id.</returns>
122         /// <privilege>http://tizen.org/privilege/account.read</privilege>
123         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given account id</exception>
124         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
125         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
126         public static Account GetAccountById(int accountId)
127         {
128             Account account = Account.CreateAccount();
129             IntPtr handle = account.Handle;
130             AccountError res = (AccountError)Interop.AccountService.QueryAccountById(accountId, out handle);
131             if (res != AccountError.None)
132             {
133                 throw AccountErrorFactory.CreateException(res, "Failed to get accounts from the database for account id: " + accountId);
134             }
135
136             account.Handle = handle;
137             return account;
138         }
139
140         /// <summary>
141         /// Retrieves all AccountProviders details from the account database.
142         /// </summary>
143         /// <returns>List of AccountProviders</returns>
144         /// <privilege>http://tizen.org/privilege/account.read</privilege>
145         /// <exception cref="InvalidOperationException">In case of any DB error</exception>
146         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
147         public static IEnumerable<AccountProvider> GetAccountProviders()
148         {
149             List<string> values = new List<string>();
150             List<AccountProvider> providers = new List<AccountProvider>();
151             Interop.AccountProvider.AccountProviderCallback accountCallback = (IntPtr handle, IntPtr data) =>
152             {
153                 AccountProvider provider = new AccountProvider(handle);
154                 values.Add(provider.AppId);
155                 provider.Dispose();
156                 return true;
157             };
158
159             AccountError res = (AccountError)Interop.AccountService.GetAllAccountproviders(accountCallback, IntPtr.Zero);
160             if (res != AccountError.None)
161             {
162                 Log.Warn(AccountErrorFactory.LogTag, "Failed to get account providers from the database");
163                 throw AccountErrorFactory.CreateException(res, "Failed to get account providers from the database");
164             }
165
166             foreach (string val in values)
167             {
168                 AccountProvider provider = GetAccountProviderByAppId(val);
169                 providers.Add(provider);
170             }
171
172             return providers;
173         }
174
175         /// <summary>
176         /// Retrieves the account provider information with application Id.
177         /// </summary>
178         /// <param name="appId">Application Id.</param>
179         /// <returns>The AccountProvider instance associated with the given application Id.</returns>
180         /// <privilege>http://tizen.org/privilege/account.read</privilege>
181         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given appid</exception>
182         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
183         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
184         public static AccountProvider GetAccountProviderByAppId(string appId)
185         {
186             IntPtr handle;
187             Interop.AccountProvider.Create(out handle);
188             AccountError err = (AccountError)Interop.AccountService.GetAccountProviderByAppId(appId, out handle);
189             if (err != AccountError.None)
190             {
191                 throw AccountErrorFactory.CreateException(err, "Failed to GetAccountProviderByAppId");
192             }
193
194             AccountProvider provider = new AccountProvider(handle);
195             return provider;
196         }
197
198         /// <summary>
199         /// Retrieves all the account providers information with feature.
200         /// </summary>
201         /// <param name="feature">The capability value to search for account providers.</param>
202         /// <returns>Retrieves AccountProviders information with the capability name.</returns>
203         /// <privilege>http://tizen.org/privilege/account.read</privilege>
204         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given feature</exception>
205         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
206         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
207         public static IEnumerable<AccountProvider> GetAccountProvidersByFeature(string feature)
208         {
209             List<string> values = new List<string>();
210             List<AccountProvider> providers = new List<AccountProvider>();
211             Interop.AccountProvider.AccountProviderCallback providerCallback = (IntPtr handle, IntPtr data) =>
212             {
213                 AccountProvider provider = new AccountProvider(handle);
214                 values.Add(provider.AppId);
215                 provider.Dispose();
216                 return true;
217             };
218
219             AccountError err = (AccountError)Interop.AccountService.GetAccountProviderByFeature(providerCallback, feature, IntPtr.Zero);
220             if (err != AccountError.None)
221             {
222                 throw AccountErrorFactory.CreateException(err, "Failed to GetAccountProviderByFeature");
223             }
224
225             foreach (string val in values)
226             {
227                 AccountProvider provider = GetAccountProviderByAppId(val);
228                 providers.Add(provider);
229             }
230
231             return providers;
232         }
233
234         /// <summary>
235         /// Inserts into the Database with the new account Infomration.
236         /// </summary>
237         /// <param name="account">New Account instance to be added.</param>
238         /// <privilege>http://tizen.org/privilege/account.read</privilege>
239         /// <privilege>http://tizen.org/privilege/account.write </privilege>
240         /// <exception cref="InvalidOperationException">In case of any DB error</exception>
241         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
242         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
243         /// <exception cref="OutOfMemoryException"> In case of OutOfMemory error.</exception>
244         public static int AddAccount(Account account)
245         {
246             if (account == null)
247             {
248                 throw AccountErrorFactory.CreateException(AccountError.InvalidParameter, "Failed to AddAccount");
249             }
250
251             int id = -1;
252             AccountError err = (AccountError)Interop.AccountService.AddAccount(account.Handle, out id);
253             if (err != AccountError.None)
254             {
255                 throw AccountErrorFactory.CreateException(err, "Failed to AddAccount");
256             }
257
258             return id;
259         }
260
261         /// <summary>
262         /// Updates the account details to the account database.
263         /// </summary>
264         /// <param name="account">account instance to be updated.</param>
265         /// <privilege>http://tizen.org/privilege/account.read</privilege>
266         /// <privilege>http://tizen.org/privilege/account.write </privilege>
267         /// <exception cref="InvalidOperationException">In case of any DB error </exception>
268         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
269         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
270         /// <exception cref="OutOfMemoryException"> In case of OutOfMemory error.</exception>
271         public static void UpdateAccount(Account account)
272         {
273             if (account == null)
274             {
275                 throw AccountErrorFactory.CreateException(AccountError.InvalidParameter, "Failed to UpdateAccount");
276             }
277
278             AccountError err = (AccountError)Interop.AccountService.UpdateAccountToDBById(account.Handle, account.AccountId);
279             if (err != AccountError.None)
280             {
281                 throw AccountErrorFactory.CreateException(err, "Failed to UpdateAccount");
282             }
283         }
284
285         /// <summary>
286         /// Deletes the account information from the Database.
287         /// </summary>
288         /// <param name="account">Account instance to be deleted from the database.</param>
289         /// <privilege>http://tizen.org/privilege/account.read</privilege>
290         /// <privilege>http://tizen.org/privilege/account.write </privilege>
291         /// <exception cref="InvalidOperationException">In case of any DB error </exception>
292         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
293         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
294         public static void DeleteAccount(Account account)
295         {
296             if (account == null)
297             {
298                 throw AccountErrorFactory.CreateException(AccountError.InvalidParameter, "Failed to DeleteAccount");
299             }
300
301             AccountError err = (AccountError)Interop.AccountService.DeleteAccountById(account.AccountId);
302             if (err != AccountError.None)
303             {
304                 throw AccountErrorFactory.CreateException(err, "Failed to delete the account by Id: " + account.AccountId);
305             }
306         }
307
308         /// <summary>
309         /// Deletes an account from the account database by user name.
310         /// </summary>
311         /// <param name="userName">The user name of the account to delete.</param>
312         /// <param name="packageName">The package name of the account to delete.</param>
313         /// <privilege>http://tizen.org/privilege/account.read</privilege>
314         /// <privilege>http://tizen.org/privilege/account.write </privilege>
315         /// <exception cref="InvalidOperationException">In case of any DB error</exception>
316         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
317         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
318         public static void DeleteAccount(string userName, string packageName)
319         {
320             AccountError err = (AccountError)Interop.AccountService.DeleteAccountByUser(userName, packageName);
321             if (err != AccountError.None)
322             {
323                 throw AccountErrorFactory.CreateException(err, "Failed to delete the account by userName: " + userName);
324             }
325         }
326
327         /// <summary>
328         /// Deletes an account from the account database by package name.
329         /// </summary>
330         /// <param name="packageName">The package name of the account to delete.</param>
331         /// <privilege>http://tizen.org/privilege/account.read</privilege>
332         /// <privilege>http://tizen.org/privilege/account.write </privilege>
333         /// <exception cref="InvalidOperationException">In case of any DB error</exception>
334         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
335         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
336         public static void DeleteAccount(string packageName)
337         {
338             AccountError err = (AccountError)Interop.AccountService.DeleteAccountByPackage(packageName);
339             if (err != AccountError.None)
340             {
341                 throw AccountErrorFactory.CreateException(err, "Failed to delete the account by package name: " + packageName);
342             }
343
344         }
345
346         /// <summary>
347         /// Retrieves all accounts with the given user name.
348         /// </summary>
349         /// <param name="userName">The user name to search .</param>
350         /// <returns>Accounts list matched with the user name</returns>
351         /// <privilege>http://tizen.org/privilege/account.read</privilege>
352         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given username</exception>
353         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
354         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
355         public static IEnumerable<Account> GetAccountsByUserName(string userName)
356         {
357             List<Account> accounts = new List<Account>();
358             List<int> values = new List<int>();
359             Interop.Account.AccountCallback accountCallback = (IntPtr handle, IntPtr data) =>
360             {
361                 Account account = new Account(handle);
362                 values.Add(account.AccountId);
363                 account.Dispose();
364                 return true;
365             };
366
367             AccountError err = (AccountError)Interop.AccountService.QueryAccountByUserName(accountCallback, userName, IntPtr.Zero);
368             if (err != AccountError.None)
369             {
370                 throw AccountErrorFactory.CreateException(err, "Failed to GetAccountByUserName");
371             }
372
373             foreach (int i in values)
374             {
375                 Account account = AccountService.GetAccountById(i);
376                 accounts.Add(account);
377             }
378
379             return accounts;
380         }
381
382         /// <summary>
383         /// Retrieves all accounts with the given package name.
384         /// </summary>
385         /// <param name="packageName"> The package name to Search</param>
386         /// <returns>Accounts list matched with the package name</returns>
387         /// <privilege>http://tizen.org/privilege/account.read</privilege>
388         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given package name</exception>
389         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
390         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
391         public static IEnumerable<Account> GetAccountsByPackageName(string packageName)
392         {
393             List<Account> accounts = new List<Account>();
394             List<int> values = new List<int>();
395             Interop.Account.AccountCallback accountCallback = (IntPtr handle, IntPtr data) =>
396             {
397                 Account account = new Account(handle);
398                 values.Add(account.AccountId);
399                 account.Dispose();
400                 return true;
401             };
402
403             AccountError err = (AccountError)Interop.AccountService.QueryAccountByPackageName(accountCallback, packageName, IntPtr.Zero);
404             if (err != AccountError.None)
405             {
406                 throw AccountErrorFactory.CreateException(err, "Failed to GetAccountByPackageName");
407             }
408
409             foreach (int i in values)
410             {
411                 Account account = AccountService.GetAccountById(i);
412                 accounts.Add(account);
413             }
414
415             return accounts;
416         }
417
418         /// <summary>
419         /// Retrieves all accounts with the given cpability type.
420         /// </summary>
421         /// <param name="type"> Capability type</param>
422         /// <returns>Accounts list matched with the capability type</returns>
423         /// <privilege>http://tizen.org/privilege/account.read</privilege>
424         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given capability type</exception>
425         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
426         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
427         public static IEnumerable<Account> GetAccountsByCapabilityType(string type)
428         {
429             List<Account> accounts = new List<Account>();
430             List<int> values = new List<int>();
431             Interop.Account.AccountCallback accountCallback = (IntPtr handle, IntPtr data) =>
432             {
433                 Account account = new Account(handle);
434                 values.Add(account.AccountId);
435                 account.Dispose();
436                 return true;
437             };
438
439             AccountError err = (AccountError)Interop.AccountService.GetAccountByCapabilityType(accountCallback, type, IntPtr.Zero);
440             if (err != AccountError.None)
441             {
442                 throw AccountErrorFactory.CreateException(err, "Failed to GetAccountByCapabilityType");
443             }
444
445             foreach (int i in values)
446             {
447                 Account account = AccountService.GetAccountById(i);
448                 accounts.Add(account);
449             }
450
451             return accounts;
452         }
453
454         /// <summary>
455         /// Retrieves all capabilities with the given account
456         /// </summary>
457         /// <param name="accountId">account instance</param>
458         /// <returns>Capabilities list as Dictionary of Capability type and State.</returns>
459         /// <privilege>http://tizen.org/privilege/account.read</privilege>
460         /// <exception cref="InvalidOperationException">In case of any DB error or record not found for given account id</exception>
461         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
462         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
463         public static Dictionary<string, CapabilityState> GetCapabilitiesById(int accountId)
464         {
465             Dictionary<string, CapabilityState> capabilities = new Dictionary<string, CapabilityState>();
466             Interop.Account.AccountCapabilityCallback capabilityCallback = (string type, int capabilityState, IntPtr data) =>
467             {
468                 capabilities.Add(type, (CapabilityState)capabilityState);
469                 return true;
470             };
471
472             AccountError err = (AccountError)Interop.AccountService.QueryAccountCapabilityById(capabilityCallback, accountId, IntPtr.Zero);
473             if (err != AccountError.None)
474             {
475                 throw AccountErrorFactory.CreateException(err, "Failed to GetAllCapabilitiesById");
476             }
477
478             return capabilities;
479         }
480
481         /// <summary>
482         /// Gets the count of accounts in the account database.
483         /// </summary>
484         /// <returns>The number of accounts in the database</returns>
485         /// <privilege>http://tizen.org/privilege/account.read</privilege>
486         /// <exception cref="InvalidOperationException">In case of any DB error </exception>
487         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
488         public static int GetAccountsCount()
489         {
490             int count = 0;
491             AccountError err = (AccountError)Interop.AccountService.GetAccountCount(out count);
492             if (err != AccountError.None)
493             {
494                 throw AccountErrorFactory.CreateException(err, "Failed to GetAccountCount");
495             }
496
497             return count;
498         }
499
500         /// <summary>
501         /// Updates the sync status of the given account.
502         /// </summary>
503         /// <param name="account"> Account for which sync status needs to be updated</param>
504         /// <param name="status">Sync State</param>
505         /// <privilege>http://tizen.org/privilege/account.read</privilege>
506         /// <privilege>http://tizen.org/privilege/account.write</privilege>
507         /// <exception cref="InvalidOperationException">In case of any DB error </exception>
508         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
509         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
510         public static void UpdateSyncStatusById(Account account, AccountSyncState status)
511         {
512             AccountError err = (AccountError)Interop.AccountService.UpdateAccountSyncStatusById(account.AccountId, (int)status);
513             if (err != AccountError.None)
514             {
515                 throw AccountErrorFactory.CreateException(err, "Failed to UpdateSyncStatusById");
516             }
517         }
518
519         private static readonly Interop.AccountService.SubscribeCallback s_accountUpdatedCallback = (string eventType, int accountId, IntPtr userData) =>
520         {
521             AccountSubscriberEventArgs eventArgs = new AccountSubscriberEventArgs(eventType, accountId);
522             s_accountUpdated?.Invoke(null, eventArgs);
523             return true;
524         };
525
526         private static Interop.AccountService.SafeAccountSubscriberHandle s_subscriberHandle;
527
528         private static event EventHandler<AccountSubscriberEventArgs> s_accountUpdated;
529         /// <summary>
530         /// ContentUpdated event is triggered when the media item info from DB changes.
531         /// </summary>
532         /// <remarks>
533         /// ContentUpdate event is triggered if the MediaInformaion updated/deleted or new Inforamtion is Inserted.
534         /// </remarks>
535         /// <param name="sender"></param>
536         /// <param name="e">A ContentUpdatedEventArgs object that contains information about the update operation.</param>
537         /// <privilege>http://tizen.org/privilege/account.read</privilege>
538         /// <exception cref="InvalidOperationException">In case of any DB error </exception>
539         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
540         /// <exception cref="UnauthorizedAccessException"> In case of privilege not defined.</exception>
541         public static event EventHandler<AccountSubscriberEventArgs> AccountUpdated
542         {
543             add
544             {
545                 if (s_accountUpdated == null)
546                 {
547                     if (s_subscriberHandle == null)
548                     {
549                         Interop.AccountService.CreateAccountSubscriber(out s_subscriberHandle);
550                     }
551
552                     AccountError ret = (AccountError)Interop.AccountService.RegisterSubscriber(s_subscriberHandle, s_accountUpdatedCallback, IntPtr.Zero);
553
554                     if (ret != AccountError.None)
555                     {
556                         throw AccountErrorFactory.CreateException(ret, "Error in callback handling");
557                     }
558                 }
559
560                 s_accountUpdated += value;
561             }
562
563             remove
564             {
565                 s_accountUpdated -= value;
566                 if (s_accountUpdated == null)
567                 {
568                     AccountError ret = (AccountError)Interop.AccountService.UnregisterSubscriber(s_subscriberHandle);
569                     if (ret != AccountError.None)
570                     {
571                         throw AccountErrorFactory.CreateException(ret, "Error in callback handling");
572                     }
573                     s_subscriberHandle = null;
574                 }
575             }
576         }
577
578     }
579 }