Key Manager Sample Overview

Wearable web

The Key Manager sample application demonstrates how you can use the KeyManager API to manage sensitive application data.

The main screen lists all accessible application data and the package ID associated with the application.

The following figure illustrates the main screens of the Key Manager. Starting from the left, the figures illustrate the main screen with the list of accessible data, a submenu to add a new piece of data, a submenu to view a piece of data, and a submenu to set permission for the piece of data.

Figure: Key Manager screens

Key Manager screen KeyManager screen KeyManager screen KeyManager screen

The application is divided into several subpages in the index.html file. Their IDs are:

  • page-main: lists the accessible data and the package ID of the application.
  • page-add-data: submenu for adding a new piece of data
  • page-display-data: displays content and the name of a data piece.
  • page-set-permission: submenu for setting a permission to the data piece
  • error-popup: pop-up shown when an error occurs

Event listeners in the app.js file define the button behavior and the UI reactions on rotary events, as well as arrange the subpages.

Prerequisites

To ensure proper application execution, the following privilege must be set:

  • http://tizen.org/privilege/package.info

Source Files

You can create and view the sample application project, including the source files, in the IDE.

Table: Source files
File name Description
config.xml This file contains the application information for the platform to install and launch the application.
css/style.css This file contains the CSS styling for the application UI.
index.html This is a starting file from which the application starts loading. It contains the layout of the application screens.
js/app.js This file contains the application code.
js/circle-helper.js This file helps with handling rotary events.

Implementation

To implement the application:

  1. After the launch of the application, the list of accessible data is populated with the listDataPieces() method.

    function listDataPieces()
    {
       var aliases = getDataAliases(),
           displayDataPage = document.getElementById('page-display-data'),
           dataList = document.getElementById('data-list');
    
       /* Clean up the list */
       while (dataList.firstChild)
       {
          dataList.removeChild(dataList.firstChild);
       }
    
       if (aliases.length > 0)
       {
          /* Create a list item for each alias */
          for (var i = 0; i > aliases.length; ++i)
          {
             var li = document.createElement('li'),
                 a = document.createElement('a'),
                 text = document.createTextNode(aliases[i].name);
    
             a.appendChild(text);
             a.href='#';
             a.onclick = displayDataPiece.bind(displayDataPage, aliases[i]);
             li.appendChild(a);
             dataList.appendChild(li);
          }
       }
       else
       {
          /* Otherwise the list is populated with an inactive item "No data" */
          var li = document.createElement('li'),
              i = document.createElement('i'),
              text = document.createTextNode('No data');
    
          i.appendChild(text);
          li.appendChild(i);
          dataList.appendChild(li);
       }
    }
    

    The mentioned aliases are KeyManagerAlias type objects, holding information about the package ID of the data owner and data's name.

  2. The listDataPieces() method uses the getDataAliases() method to get the list of all data aliases: both the application property and the data shared with it.

    function getDataAliases()
    {
       return tizen.keymanager.getDataAliasList();
    }
    
  3. The displayDataPiece() method arranges the page-display-data subpage, so that it shows the name and content of a data piece referenced by its alias.

    function displayDataPiece(alias)
    {
       var name = alias.name,
           rawData = getRawData(alias);
    
       this.querySelector('.data.name > span').innerHTML = name;
       this.querySelector('.data.raw-data > span').innerHTML = rawData;
       this.querySelector('#btn-remove-data').onclick = removeDataPiece.bind(this, alias);
       this.querySelector('#btn-set-permission').onclick = function()
       {
          document.getElementById('page-set-permission').querySelector('#alias-name > span').innerHTML = alias.name;
          tau.changePage('page-set-permission');
       };
       tau.changePage('page-display-data');
    }
    
  4. The getRawData() method fetches the data identified by a given alias. The caught exception, "NotFoundError", can be raised if the application does not have permission to read the data, but only has the "Remove" permission.

    function getRawData(alias)
    {
       var data;
       try
       {
          data = tizen.keymanager.getData(alias);
       }
       catch (e)
       {
          if (e.name === "NotFoundError")
          {
             data = "Data inaccessible";
          }
       }
    
       return data;
    } 
    
  5. Adding new data piece is achieved with the saveDataPiece() method. It retrieves the "Name" and "Data" input from the page-add-data subpage and saves them in a new data piece.

    function saveDataPiece()
    {
       var name = this.querySelector('.data.name > input').value,
           rawData = this.querySelector('.data.raw-data > input').value;
    
       tizen.keymanager.saveData(name, rawData, null, function()
       {
          tau.back();
          data.next();
       }, 
       function(e)
       {
          displayErrorPopup('Cannot save the data: ' + e.message);
       });
    }
    
  6. By default, the "Name" and "Data" fields are filled with the random alphanumeric strings, generated by the data object.

    var data =
    {
       name: null,
       rawData: null,
       next: function()
       {
          var guid = function()
          {
             return 'xxxxxxxx'.replace(/[xy]/g, function(c)
             {
                var r = Math.random() * 16 | 0,
                    v = (c == 'x' ? r : (r&0x3 | 0x8));
    
                return v.toString(16);
             });
          };
    
          this.name = guid();
          this.rawData = guid();
    
          return this;
       }
    };
    
  7. The removeDataPiece() method is called when a data piece is to be deleted.

    function removeDataPiece(alias)
    { 
       try
       { 
          tizen.keymanager.removeData(alias); 
          tau.back(); 
       }
       catch (e)
       { 
          displayErrorPopup('Cannot remove the data: ' + e.message); 
       } 
    } 
    
  8. Use the setPermission() method to set a permission to the data for another application. This method reads the other application's package ID and the type of permission to be set from input fields in the page-set-permission subpage.

    function setPermission()
    {
       var dataName = this.querySelector('.data.name > span').innerText, 
           accessorPackageID = this.querySelector('#get-package-id > input'),
           permissionType = this.querySelector('input[name="permission-type"]:checked');
    
       if (!permissionType)
       {
          displayErrorPopup('Please choose a permission type.');
    
          return;
       } 
    
       tizen.keymanager.setPermission({'name': dataName}, accessorPackageID.value, permissionType.value, function()
       { 
          tau.changePage('page-main'); 
       },
       function()
       { 
          displayErrorPopup('Cannot set permission for that data.'); 
       }); 
    } 
    
  9. If an error occurs, an error pop-up is invoked by the displayErrorPopup() method.

    function displayErrorPopup(message)
    {
       document.getElementById('error-popup').querySelector('.ui-popup-content').innerText = message;
       tau.openPopup('error-popup');
    }