Table of contents

GS5.js

The Javascript APIs of gs5.js is grouped as following:

  • gs: Root object of SoftwareShield apis
  • gs.core: License accessing
  • gs.ui: UI control
  • gs.video: Video player
  • gs.app: App control
  • gs.os: Native operating system features
  • gs.single: Helper api for project with a single entity
  • gs.util: Utility apis for most commonly used functions

The source list here is just for quick online reference, please refer to "How to get the latest SDK?" to get the original SDK files. The SDK/Javascript files are in "Lang\Javascript" folder.

General Information

  • gs.version: SDK Version
    The SDK version of SoftwareShield license kernel in string format.

  • gs.productName: Product Name

    The string of product name defined in the SoftwareShield IDE.

    This value is used by built-in UI template as Windows title.

    When customizing the HTML page, you are free to ignore this value and use any hard-coded string displayed on the UI. For example, you can detect the current system default locale (locale support) and use an user-friendly string as product name.

  • gs.productId: Product ID

    The unique string id of product-id defined in the SoftwareShield IDE.

  • gs.buildId: Product Build ID

    The unique integer Build-ID of this application release.

   var sdkVersion = gs.version; //sdkVersion = "5.3.2.0"
   var appId = gs.productName + '(build: ' + gs.buildId + ', sdk version: ' + sdkVersion + ')';
   alert(appId); // My Test Game (build: 8, sdk version: 5.3.2.0)  

Get Entity

In SoftwareShield license project, you can define multiple entities to protect, each of them is associated with a license. SoftwareShield SDK encapsulates the license accessing apis in name space gs.core. The entities and licenses are mapped to corresponding Javascript objects so you can access their properties and member functons to access the current licensing status.

  • Enumerate All Entities

    In Javascript, you can enumerate all defined entities as following:

     for(i = 0; i < gs.core.getTotalEntityCount(); i++){
       //get each entity object by its index
       var entity = gs.core.getEntityByIndex(i); 
  • Get Entity By EntityId

    Given the unique entity-id defined in the license project, you can get the entity directly as following:

       //get the entity object by its entity-id
       var entity = gs.core.getEntityById('a4c33d4c-9239-4c66-899b-b6223ef40b72'); 
  • Single Entity: The most simple case

    By default, SoftwareShield automatically defines an entity when creating a new project. If it suffices your requirement then there is only one entity in your license project. In this case, accessing this entity is quite easy:

       //With gs.single helper
       var entity = gs.single.getEntity();

       //Single entity is the first entity with index = 0
       var entity = gs.core.getEntityByIndex(0);
  • Current Entity

    When an entity is to be accessed in code, the onStart UI page (onStart.htm by default) will pop up allowing customers to input license code if the entity is not activated yet; if there are multiple entities in your license project, how do we know which entity is being accessed? in SoftwareShield term, this entity causing the onStart UI launches is called

   var entity = gs.core.getCurrentEntity();

Query License Status

Now that you have retrieved the entity object, you can access its information by reading its properties and calling its member functions.

  • Entity Properties

    An entity object has the following properties:

   var entityName = entity.name; // Entity name defined in license project
   var entityId = entity.id; // Unique entity-id
   var entityWhat = entity.what; //Long description of the entity
  • Test if entity is fully licensed, in trial mode or already expired

If your entity is associated with a trial license model (Expire by Access Times, Expire By Hard Date, Expire By Period, Expire by Duration, Expire by Session Time), you can test the entity's license status as following:

if(entity.isUnlocked()){
  //this entity is already activated / fully purchased.
  //app should run in full featured mode for this entity (game level, app module, etc.)...
  run_in_full_featured_mode();
} else if (entity.isLocked()){
  //this entity is locked or trial already expired.
  //we may pop up info to prompt for purchase.
  cannot_run();
} else {
  //this entity still in trial period or duration
  run_in_trial_mode();
}

If your entity is using License Model Always Lock, then the logic can be simplied as:

if(entity.isUnlocked()){
  //this entity is already activated / fully purchased.
  //app should run in full featured mode for this entity (game level, app module, etc.)...
  run_in_full_featured_mode();
} else {
  //this entity is still locked, we need a license to continue.
  //we may pop up info to prompt for purchase.
  cannot_run();
}

Query License Model Parameters

In the above section, we have detected that an entity is still in trial mode, so in order to display proper license information to end user on app UI, such as tell the game player how many trial time left before the game will stop running, we must be able to get more details of the license model.

  • Get License Object Given an entity, it is quite simple to retrive the license object attached to this entity:
var lic = entity.getLicense();

Now that the license object is ready, we can inspect it in various perspectives:

  • Get License Model Type

As a developer we have designed the license project in SoftwareShield IDE before, so we should have known which kind of license model being used for an entity. However, if you are developing a universal logic to parse any entity, it is helpful to find out the license model type being bundled with the input entity:

For example, for Expire By Period, its LicenseID is "gs.lm.expire.period.1", so by comparing the license id you can figure out the correct license model type to inspect further.

var licId = lic.id; //=> "gs.lm.expire.period.1"
var licName = lic.name; //=>"Expire By Period"
var licWhat = lic.what; //=> "Protected entity expires after it has been accessed more than a preset time period."
  • Get License Model Parameters

Now we have known which license model to inspect, let's retrieve the license parameters according to its model type:

Expire by Access Times

This license model (Expire by Access Times) has two parameters of int type: "usedTimes" and "maxAccessTimes"

var usedTimes = lic.getParamValue("usedTimes");
var maxAccessTimes = lic.getParamValue("maxAccessTimes");

//How many times left the app can launch in trial mode? 
var how_many_access_left = maxAccessTimes - usedTimes;

Expire By Hard Date

This model (Expire By Hard Date) is a bit complex since it have three different use cases, in this tutorial we only demonstrate the most commonly used one: "Expire After", in this case, the license has a predefined expiry date "timeEnd", the app trial mode expires after this date.

var expiryDate = lic.getParamValue("timeEnd");

console.log("Local: " +  expiryDate); //=> "Wed Sep 30 2015 00:00:00 GMT-0700 (Pacific Daylight Time)"
console.log("UTC: " +  expiryDate.toUTCString()); //=> "Wed, 30 Sep 2015 07:00:00 GMT"

The interest part is that SoftwareShield SDK api always returns UTC date time value, javascript is very easy to convert to local date time.

Expire By Period

This license model (Expire By Period) has a UTC datetime parameter "timeFirstAccess", specify the timestamp the entity is first accessed, and an integer parameter "periodInSeconds", specify the total trial period allowed. The following code tries to figure out when the license will expire and how many trial time left before expire.

//Total trial period in seconds
var periodInSeconds = lic.getParamValue("periodInSeconds");

//Figure out when the entity is first accessed (aka. entity.beginAccess() is first called)
//if never accessed before, the _timeFirstAccess_ parameter won't hold a valid datetime and the api returns a null object

var timeFirstAccess = lic.getParamValue("timeFirstAccess");
if(timeFirstAccess != null){  
  //accessed before, so we can calculate the expiry date
  var expiryDate = new Date(timeFirstAccess.getTime() + periodInSeconds * 1000);
  
  //How many trial time left?
  var now = new Date();
  var timeLeftInSeconds = ( expiryDate - now )/1000;
} else {
  //Never accessed, the expiry date is still unknown!

  //How many trial time left = full trial period.
  var timeLeftInSeconds = periodInSeconds;
}

The interesting part of the above code is that: if the "timeFirstAccess" does not hold a valid timestamp (the default value is null), which occurs when the entity is never accessed before, we cannot deduce the exact expiry date, however we can deduce how many time left before expire.

Expire by Duration

This license model (Expire by Duration) is simple, it just adds up all elapsed trial time cumulatively (in "usedDurationInSeconds") until the total trial time exceeds the pre-defined maximum value ("maxDurationInSeconds"). We cannot figure out the expiry date.

//Total trial period in seconds
var usedDurationInSeconds = lic.getParamValue("usedDurationInSeconds");
var maxDurationInSeconds = lic.getParamValue("maxDurationInSeconds");

//How many trial time left?
var timeLeftInSeconds = maxDurationInSeconds - usedDurationInSeconds;

Expire by Session Time

This license model (Expire by Session Time) allows an entity can always be accessed (never expire) but in a limited time, we can get the session time left but cannot get the expiry date.

var sessionTimeUsed = lic.getParamValue("sessionTimeUsed");
var maxSessionTime = lic.getParamValue("maxSessionTime");

//How many trial time left?
var timeLeftInSeconds = maxSessionTime - sessionTimeUsed;

Helper FunctionL Get Trial Time Left Information

In the above section you have learned how to read license information for each license type, it is a quite common requirement that you want to display how many trial time left before expiration on your license UI, SDK/Javascript implements a member function of Entity object as a helper to let you retrieve the trial information easily.

Entity.getTimeLeft()

var timeLeft = entity.getTimeLeft();

The returned timeLeft value can be interpreted per license type as following:

License Type timeLeft Data Type Memo
Expire by Access Times integer How many launch times left the app can run app in trial mode?
Expire By Hard Date float How many trial time left (in seconds) before expiry date
Expire By Period float How many trial time left (in seconds) before expiry date
Expire by Duration integer How many trial time left (in seconds) before expiry date
Expire by Session Time integer How many trial time left (in seconds) before the current app session expires

The getTimeLeft() function will throw exception if the entity's license type is not of a trial license model!

Entity.getTimeLeftString()

While the Entity.getTimeLeft() is very handy to get trial information, its returned value has to be parsed according to different license type. SDK/Javascript also implements another useful member function of Entity object as a helper to parse the timeLeft value for you as simple strings.

var timeLeftStr = entity.getTimeLeftString();

var timeLeft = timeLeft.value;

The returned timeLeftStr object has three properties:

  • value: The original timeLeft value from getTimeLeft();
  • numberString: parsed string of day(s)/hours(s)/minutes(s), etc.
  • textString: parsed string of unit
License Type numberString textString
Expire by Access Times launch times left, ex: "1","8" "Access Left", "Accesses Left"
Expire By Hard Date, Expire By Period, Expire by Duration, Expire by Session Time trial time left (in day/hour/minute/second), ex: "2" ,"30" "Day(s) Left", "Hour(s) Left", "Minute(s) Left", "Second(s) Left"
License Model Always Run "--" "Always Run"
License Model Always Lock "--" "Always Locked"

Activation

There are two methods to activate your app, online and offline.

  • Online Activation

After user've made purchase of your app, you send a serial number to the customer as a proof of valid customer and the key to activate your app.

if(core.isServerAlive()){
  var success = gs.core.applySN(serial);
}else{
  console.log("license server is not available!");
  //optionally fall back to offline activation...
}
  • Offline Activation

In order to do offline activation, we need to go through three steps:

  1. Generate Request Code
var requestCode = gs.core.getDummyRequestCode();

We are using dummy request code because the license server can deduce all valid actions from the customer's serial number.

  1. Get License Code from License Server

You display the request code on UI, asking the customer to contact your support team for a valid license code, or if possible, let the customer uses another machine (or a mobile device) to generate the license code by himself/herself via the app's public App Web Activator.

You can also develop a simple web page on your own web server, implementing the license code generating UI based on CheckPoint2 API (ref: License Code Generation).

  1. Apply License Code

Once the user input a license code, we can apply it to the app:

var licenseCode = readLicenseCodeFromUI(); //user input the license code.
var success = gs.core.applyLicenseCode(licenseCode, serial);

Revoke License

SoftwareShield SDK allows you to revoke serial numbers to license server so that the revoked serial numbers can be reused in another machine or the same machine (after hardware upgrade, system re-install, etc.)

  1. Revoke Single Serial Number
var serialToRevoke;
var success = gs.core.revokeSN(serialToRevoke);

After successful revoke, all those entities previously unlocked by this serial are locked.

  1. Revoke All Serial Numbers
var success = gs.core.revokeApp();

After successful revoke, all previously unlocked entities are locked.

gs.app: Application control

Properties

  • gs.app.rootPath : The full path to the app install directory.

  • gs.app.lmappPath : The full path to the directory the license UI files are installed.

  • gs.app.buyNowURL : The app's purchase URL.

In UI HTML/Javascript pages, you can control if the app should continue running, restart, or simply terminate immediately.

How to continue running the application?

If your javascript logic detects the license is permitted, the app can run as following:

gs.app.play();

Result:

  • Current License UI is closed;
  • If app is starting, continue launching app; (pre-app UI)
  • If app is exiting, restarts the app; (post-app UI)

When activating app on either pre-app UI or post-app UI, you can call gs.app.play() to launch (pre-app UI) or restart (post-app UI) app. SoftwareShield will detect the current app status and launches or restarts app properly.

How to restart the application?

You may want to restart app when an license error is fixed or a serial number has been applied and your app needs restarting to run in full-featured mode:

gs.app.restart();

Result:

  • Current License UI is closed;
  • app is restarted;

How to terminate the application?

You can terminate app in Javascript as following:

var ec = 10; //app exit code
gs.app.exit(ec);

Result:

  • Current License UI is closed;
  • app is terminate;

When app exiting from post-app UI, it terminates immediately, otherwise if this api is called from pre-app UI, the pre-defined app-exiting UI might pops up according to the project's UI Behavior.

gs.ui: UI control

The functions in this section allows you to fully control your license UI.

UI Title

By default, the project's Product Name is used as UI title, however you can change the title as following:

gs.ui.setTitle('My App');

It is useful when you are developing a multilingual software that the UI should be localized according to the customer's active locale.

UI Loading Timeout

The maximum waiting time (in seconds) before the UI becomes visible. It makes sure the app get a visual feedback (even an incomplete UI content) instead of waiting for your javascript code executing or page loading endlessly, which might seem odd if the user can see nothing after the app icon is double-clicked.

//get the current load timeout value
var timeout = gs.ui.loadTimeOut();

//set the page loading timeout to 15 seconds
gs.ui.setLoadTimeOut(15);

The default value is 20 seconds. If your UI pages are deployed (or embedded) with app, it is good enough, if your UI pages are fetched from web server, the page loading timeout value is important. To get a better user experience it is better to use a hybrid scheme, the startup page template is a local one, its content can be downloaded from web server via AJAX after the UI becomes visible by calling gs.ui.show().

You can setup the default page load time out value in IDE (ref: Page Loading Time Out).

Purchase UI

When user clicks the Buy Now link / button, you can redirect the customer to app's purchase web site (payment UI hosted in app store) in two ways:

  • In-App Purchase
$('buy-now-link')..on('click', function() {
   window.location = "https://www.myapp.com/appstore/";
});
  • Out-App Purchase
$('buy-now-link')..on('click', function() {
   gs.util.launchDefaultBrowser("https://www.myapp.com/appstore/");
});

Since SDK v5.3.6, the BuyNowURL is saved in local license file, you can also enable "In-App Purchase" in UI Options dialog box:

As a result, you can unify the above two cases as following:

$('buy-now-link')..on('click', function() {
   gs.ui.purchase();
});

The gs.ui.purchase() api will detect the current purchase settings ( BuyNowURL and In/Out-App Purchase) and renders the purchase UI properly.

UI Show, Hide and Close

Your javascript code runs in a context of HTML UI page, which can be visible, hidden or simply closed as following:

//show current UI
gs.ui.show();

When your javascript is running, the UI page is hidden to give you a chance to update the UI content. The page will become visible if either of the following cases occur:

  1. gs.ui.show() is called;
  2. Page loading time-out elapsed and gs.ui.hide() is not called before.
//hide current UI
gs.ui.hide();

This api is used to hide the current UI, it is rarely used since the initial visibility of UI page is hidden, however you can call it explicitly in your code so that the UI will not show up after the loading timeout timer is elapsed --- it will be closed silently in this case.

//close current UI
gs.ui.close();

Normally the license UI pops up during a process of license event handling, when the UI is closed, the event handling continues. For example, the onStart.htm pops up when the auto-start entity is going to be accessed when app launching, it is your (javascript code's) responsibility to make sure the entity has a valid license before the UI is closed, you can detect the license status and prompt for app activation if necessary; after the UI is closed, SoftwareShield runtime will check if the entity's license is valid, if not, the app will not continue launching.

Usually you do not need to call this api, the gs.app.play() / gs.app.restart() /gs.app.exit() will close the UI automatically.

UI Page Hopping

  1. Hopping between local pages or remote pages
window.location = 'activate.htm'; 
  1. Hopping from local page to remote page
//The remote page url defined in project settings, or you can use a hard-coded one as needed.
var urlbase = gs.ui.remoteUrlBase();

window.location =  urlbase + 'activate.htm'; 
  1. Hopping from remote page to local page

To jump from a page hosted on web server to a local page, we need a special api gs.ui.render()

gs.ui.render( filename, [optional] );
//The current page is a remote one, let's jump to local page...
gs.ui.render('activate.htm'); 

gs.ui.render() allows you specify some optional parameters for the page rendering:

  • title: the default UI title
gs.ui.render('activate.htm', { title: "App Activation" });
  • location: Explicitly specify where the target file is. There are three constants:
Location Memo Example
LOC_LOCAL Use local UI page gs.ui.render('activate.htm', {location: gs.ui.LOC_LOCAL});
LOC_REMOTE Use remote UI page gs.ui.render('activate.htm', {location: gs.ui.LOC_REMOTE});
LOC_AUTO (default) Search the page according to project UI settings gs.ui.render('activate.htm')

gs.os: Acess Local Operating System

SoftwareShield allows you to access client's operating system facilities in Javascript.

Operating System Name

var osName = gs.os.name;

Possible name can be: "Windows", "Mac"

Command Line Parameters

SoftwareShield has a built-in command line parameter "-showui", once specified, the javascript code in UI_HTML/onStart.htm is always executed on app launching even after the app is fully activated, so that you will have a chance to evaluate the current license status and allow customer to activate or transfer license.

//onStart.htm:

           var args = gs.os.commandLineArgs;

            if (arg[1] == "-showui") {
              Shield.WindowVisible(true);
              sessionStorage.setItem('showui', true);

              if (args[2] == "-revoke") {
                 window.location = "licenseTransfer.htm";
                 return;
              }else if (args[2] == "-activate") {
                 window.location = activateUrl;
                return;
              }
            }

To simply force the javascript code of onStart.htm executing:

  MyApp -showui

To launch directly to license transfer UI, the app is invoked as following:

  MyApp -showui -revoke

To launch directly to license activation UI, the app is invoked as following:

  MyApp -showui -activate

File and Directory

SoftwareShield allows you to access local file system from UI page, the following is the most commonly used directory apis:

API Path Example
gs.app.rootPath Where is the app installed? "C:\Users\randy\Documents\SoftwareShield\MyApp\Release\Deploy"
gs.ui.localDir / gs.app.lmappPath the absolute path to UI_HTML "C:/Users/randy/Documents/SoftwareShield/MyApp/Release/Deploy/UI_HTML/"
gs.os.homeDir The current user's home directory "C:\Users\randy"

Directory APIs

API Memo
gs.os.createDir( dir ) Create a new directory, the input dir must be in absolute path format.
gs.os.dirExists( dir ) Test if a directory exists, the input dir must be in absolute path format.

File APIs

API Memo
gs.os.fileExists( file ) Test if a file exists, the input file must be in absolute path format.
gs.os.readTextFile( file ) Read a text file and returns its content as a string.
gs.os.writeTextFile( file, content ) Write a string to a text file, its old content is replaced with the new content

Environment Variables

You can retrieve the value of environment variable in javascript as following:

//get system temporary directory
var tmpDir = gs.os.getEnvironmentVariable('TEMP');

//get the current user name
var username = gs.os.getEnvironmentVariable('USERNAME');

gs.os.clipboard: Clipboard Accessing

Copy to Clipboard:

 //Generate a request code and copy it to local clipboard
 var requestCode = gs.util.getUnlockRequestCode();
 gs.os.clipboard.copy(requestCode);

Paste from Clipboard:

  //Paste serial number from clipboard to UI page:
  $('#serial').html( gs.os.clipboard.paste() );

E-Mail Client

To spawn the default e-mail client app:

var address = 'support@myapp.com';
var title = 'support request';
var requestCode = gs.util.getUnlockRequestCode();
var content = 'I want to manual activate my app, the offline activation request code is:' + requestCode;
gs.util.mailTo( address, title, content );

Launch Default Web Browser

To launch the default web browser to a specific URL:

gs.util.launchDefaultBrowser('http://www.myapp.com');

gs.os.locale: Multilingual Support

To support multilingual UI SoftwareShield provides you the following properties:

API Memo Sample
gs.os.locale.language Default language, ref: Country & Language 'English'
gs.os.locale.country The customer's country, ref: Country & Language 'Canada'
gs.os.locale.BCP47Name Default locale, ref: BCP47 Standard 'en-CA', 'en-US', 'en-GB'

Combined with the file access apis, you can develop your license UI speaking the customer's language:

  1. Translate all supported resources in different locale and put it under UI_HTML as different file name;
  2. Detects the current locale and read the correct resource file;
  3. Update the UI with loaded locale-specific resources;

gs.os.keyboard: Keyboard Support

The javascript does not provide a reliable api to detect if a key is pressed, it relies on the key down event after your HTML page (where the javascript is hosted) is loaded, so if you want to detect if the user is pressing "Shift" key when app is double-clicked, it cannot be done properly, so SoftwareShield implements the following api to allow you to query the current key status:

bool gs.os.keyboard.isModifierKeyPressed( mkey );

Checks if the modifier key is currently being pressed.

Supported modifier keys are:

Key Memo Windows Mac
MKEY_SHIFT (1) Shift Key Yes Yes
MKEY_CONTROL (2) Control Key Yes Yes
MKEY_ALT (3) Alt Key Yes Yes
MKEY_WINDOWS (4) Windows Key Yes No
MKEY_COMMAND (5) Command Key No Yes
var isShiftKeyPressed = gs.os.keyboard.isModifierKeyPressed( gs.os.keyboard.MKEY_SHIFT );

Output Debug Message

SoftwareShield debug version will save detailed debug messages to a log file, you can use the following api to output debug messages to log file:

  gs.core.trace('*** Hello World! ***');

This api does nothing for release version of binaries.

You can detect if you are running in an app wrapped by debug version of SoftwareShield:

var runningDebugVer = gs.core.isDebugVersion();

In previous overview section, we have mentioned you can output message in javascript standard console (ref: "Log Messages"), this message will not go into the debug log file.

App Launch for the First Time

Sometimes you might want to do some initialize task or display special messages on UI when the app is launched for the very first time. You can detect if the app is being launched for the first time as following:

if(gs.core.isAppFirstLaunched()){
 alert('Hi, thanks for installation, ...');
}