/************************************************************************************************** * * ADOBE SYSTEMS INCORPORATED * Copyright 2014 Adobe Systems Incorporated * All Rights Reserved. * * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the * terms of the Adobe license agreement accompanying it. If you have received this file from a * source other than Adobe, then your use, modification, or distribution of it requires the prior * written permission of Adobe. * **************************************************************************************************/ /** AgoraLib - v7.0.0 */ /** * @class AgoraLib * * AgoraLib provides an interface to the Adobe Exchange service and Exchange plugin. * Please note that Vulcan.js is required. */ function AgoraLib() { var extensionID = window.__adobe_cep__.getExtensionId(); // GUID discussions: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);return v.toString(16);}); var that = this; var exchangeVersion; this.callerID = guid + '_' + extensionID; this.bundleID = window.__adobe_cep__.invokeSync("getBundleId", ""); //--------------------------------------- Private functions ------------------------------ this.responseCallback = function (message) { if (window.DOMParser) { var parser = new window.DOMParser(); try { var xmlDoc = parser.parseFromString(message.data, "text/xml"); var payloadNode = xmlDoc.getElementsByTagName("payload")[0]; if (payloadNode && payloadNode.childNodes[0]) { payloadNode = payloadNode.childNodes[0].nodeValue; } if (payloadNode !== null) { payloadNode = cep.encoding.convertion.b64_to_utf8(payloadNode); } console.log("Decoded payload: " + payloadNode); var payloadDoc = parser.parseFromString(payloadNode, "text/xml"); var responses = payloadDoc.getElementsByTagName("Response"); for (var i = 0; i < responses.length; i++) { var respElem = responses[i]; if (respElem) { var apiName = respElem.attributes.getNamedItem("name").nodeValue; var callerID = respElem.attributes.getNamedItem("callerID").nodeValue; console.log("This caller ID " + that.callerID + " received caller ID " + callerID); console.log("API: " + apiName); if (callerID === that.callerID) { console.log("CallerIDs match! Now removing message listener"); VulcanInterface.removeMessageListener(AgoraLib.RESPONSE_TYPE, that.responseCallback); // extract parameters var respParams = respElem.getElementsByTagName("Result"); var params = {}; for (var j = 0; j < respParams.length; j++) { var paramName = respParams[j].attributes.getNamedItem("name").nodeValue; var paramValue = respParams[j].getElementsByTagName("Value")[0].textContent; console.log("param name: " + paramName + " param value: " + paramValue); params[paramName] = paramValue; } if (apiName === AgoraLib.IS_ENTITLED) { console.log("IsEntitled callback"); var response1 = new AgoraLibResponse(params[AgoraLib.IS_ENTITLED], params[AgoraLib.STATUS], params[AgoraLib.STATUSCODE]); that.isEntitledCallback(response1); } else if (apiName === AgoraLib.GET_PURCHASE_URL) { console.log("GetPurchaseUrl callback"); var url = params.URL; var response2 = new AgoraLibResponse(url, params[AgoraLib.STATUS], params[AgoraLib.STATUSCODE]); that.getPurchaseUrlCallback(response2); } else if (apiName === AgoraLib.GET_VERSION) { console.log("GetVersion callback"); var response3 = new AgoraLibResponse(params.Version, params[AgoraLib.STATUS], params[AgoraLib.STATUSCODE]); that.exchangeVersion = params.Version; that.getVersionCallback(response3); } else if (apiName === AgoraLib.CREATE_ENTITLEMENT) { console.log("CreateEntitlement callback"); var response4 = new AgoraLibResponse("", params[AgoraLib.STATUS], params[AgoraLib.STATUSCODE]); that.createEntitlementCallback(response4); } } } } } catch(e) { console.log("AgoraLibError: " + e); } } }; this.checkVersion = function() { console.log("Checking version..."); var request = "<Request name=\"" + AgoraLib.GET_VERSION + "\" callerID=\"" + that.callerID + "\"><Parameters>"; request += "</Parameters></Request>"; var sub_payload = String.format(AgoraLib.MESSAGE_REQUEST_TEMPLATE, request); var GetVersionVulcanMessage = new VulcanMessage(AgoraLib.MESSAGE_TYPE); GetVersionVulcanMessage.setPayload(sub_payload); VulcanInterface.addMessageListener(AgoraLib.RESPONSE_TYPE, that.responseCallback); VulcanInterface.dispatchMessage(GetVersionVulcanMessage); return; }; this.continueWithCheckVersion = function() { if (!that.exchangeVersion) { that.checkVersion(); } else { var responseObject = new AgoraLibResponse(this.exchangeVersion, AgoraLib.status.success.status, AgoraLib.status.success.code); that.getVersionCallback(responseObject); } }; this.checkConnection = function(callback, ignoreACCC) { that.getVersionCallback = callback; var param = ""; var status = AgoraLib.status.internalClientError.status; var statusCode = AgoraLib.status.internalClientError.code; // CoreSync and Thor will include vulcan specifiers so we can // use the vulcan control library to detect CoreSync and Thor and launch when not running. var isInstalled = VulcanInterface.isAppInstalled("coresync"); if (!isInstalled) { console.log("CoreSync does not exist"); status = AgoraLib.status.creativeCloudNotFoundError.status; statusCode = AgoraLib.status.creativeCloudNotFoundError.code; } else { var isRunning = VulcanInterface.isAppRunning("coresync"); console.log("CoreSync running? : " + isRunning + ", should it be launched if not running? " + (ignoreACCC ? "no" : "yes")); if (!isRunning && !ignoreACCC) { // attempt to launch ACC desktop which will launch CoreSync isRunning = VulcanInterface.launchApp("creativecloud", false, ""); if (isRunning) { console.log("ACCC is now being launched"); var startedUpCallback = function(message) { console.log("ACCC started up"); VulcanInterface.removeMessageListener(AgoraLib.ACCC_STARTED_UP_MESSAGE, this); that.continueWithCheckVersion(); }; // add event listener for vulcan.SuiteMessage.any.cosy.app.StartedUp so we know CoreSync is launched and ready to receive messages VulcanInterface.addMessageListener(AgoraLib.ACCC_STARTED_UP_MESSAGE, startedUpCallback); return; } else { status = AgoraLib.status.creativeCloudFailedToLaunchError.status; statusCode = AgoraLib.status.creativeCloudFailedToLaunchError.code; } } else if (!isRunning && ignoreACCC) { // CoreSync is not running but user wants to bypass launching it. Return error to callback. status = AgoraLib.status.creativeCloudNotLaunchedError.status; statusCode = AgoraLib.status.creativeCloudNotLaunchedError.code; } else { that.continueWithCheckVersion(); return; } } var responseObject = new AgoraLibResponse(param, status, statusCode); callback(responseObject); }; // source: http://stackoverflow.com/questions/7717109/how-can-i-compare-arbitrary-version-numbers this.compareVersion = function (a, b) { var i, cmp, len, re = /(\.0)+[^\.]*$/; a = (a + '').replace(re, '').split('.'); b = (b + '').replace(re, '').split('.'); len = Math.min(a.length, b.length); for( i = 0; i < len; i++ ) { cmp = parseInt(a[i], 10) - parseInt(b[i], 10); if ( cmp !== 0 ) { return cmp; } } return a.length - b.length; }; } //--------------------------------------- Public API ------------------------------ AgoraLib.prototype = (function(){ /** * Triggers a check to determine if the current user is entitled to access the active extension. * Possible responses are True, False or Unknown. Further information about the response can be found in * the responses status and statusCode properties. For example, if the response is true, status and statusCode can * return the following combinations:\n * <ul>\n * <li>1: Perpetual purchase</li>\n * <li>2: Trial purchase</li>\n * <li>3: Subscription purchase</li>\n * <li>4: Subscription expired {date}</li>\n * </ul>\n * * This API has a dependency on VulcanInterface.js and will throw an error if it is not defined. * * @param callback The JavaScript handler function to return the AgoraLibResponse object. * @param ignoreACCC When true this API will not attempt to launch the Adobe Creative Cloud Connection application if it is not running. The default value is false. * @since 5.2.0 */ var isEntitled = function(callback, ignoreACCC) { if (typeof(Vulcan) === 'undefined') { throw 'Vulcan.js is required.'; } if (callback === null || callback === undefined) { callback = function(result){}; } if (ignoreACCC === null || ignoreACCC === undefined) { ignoreACCC = false; } this.isEntitledCallback = callback; var that = this; var success = false; // check connection this.checkConnection(function(responseObj) { console.log("isEntitled checkConnection response: " + responseObj.response + " with status: " + responseObj.status + " and statusCode: " + responseObj.statusCode); success = true; // check status and statusCode for success. if (responseObj.statusCode === "0" && that.compareVersion(responseObj.response, "1.0.0") >= 0) { console.log("isEntitled: connection check successful, now continue with isEntitled API call..."); var request = "<Request name=\"" + AgoraLib.IS_ENTITLED + "\" callerID=\"" + that.callerID + "\"><Parameters>"; request += "<Parameter name=\"BundleID\"><Value>" + that.bundleID + "</Value></Parameter>"; request += "</Parameters></Request>"; var sub_payload = String.format(AgoraLib.MESSAGE_REQUEST_TEMPLATE, request); var isEntitledVulcanMessage = new VulcanMessage(AgoraLib.MESSAGE_TYPE); isEntitledVulcanMessage.setPayload(sub_payload); VulcanInterface.addMessageListener(AgoraLib.RESPONSE_TYPE, that.responseCallback); VulcanInterface.dispatchMessage(isEntitledVulcanMessage); } else { var response = new AgoraLibResponse("Unknown", responseObj.status, responseObj.statusCode); callback(response); } }, ignoreACCC); // add a timeout and return error if response is not returned after a minute setTimeout(function(){ if (!success) { console.log("isEntitled: Request timed out"); var response = new AgoraLibResponse("Unknown", AgoraLib.status.internalClientError.status, AgoraLib.status.internalClientError.code); callback(response); } }, AgoraLib.TIMEOUT); }; /** * Calls the Adobe Exchange service for a Purchase Url for the active extension. If the request is successful the statusCode in the response will be 0. * * This API has a dependency on VulcanInterface.js and will throw an error if it is not defined. * * @param callback The JavaScript handler function to return the AgoraLibResponse object. The Response property will either be the final checkout page or the product details page (see below). * @param straightToCheckout If set to true the URL returned will be the final checkout page for this Extension on the Adobe Add-ons site. If set to false the * URL returned will be the Product details page for this Extension on the Adobe Add-ons site. Default is false. * @param ignoreACCC When true this API will not attempt to launch the Adobe Creative Cloud Connection application if it is not running. The default value is false. * @since 5.2.0 */ var getPurchaseUrl = function(callback, straightToCheckout, ignoreACCC) { if (typeof(Vulcan) === 'undefined') { throw 'Vulcan.js is required.'; } if (callback === null || callback === undefined) { callback = function(result){}; } if (ignoreACCC === null || ignoreACCC === undefined) { ignoreACCC = false; } this.getPurchaseUrlCallback = callback; straightToCheckout = (!requiredParamsValid(straightToCheckout) || straightToCheckout === '') ? false : straightToCheckout; var that = this; var success = false; // check connection this.checkConnection(function(responseObj) { success = true; console.log("getPurchaseUrl: checkConnection response: " + responseObj.response + " with status: " + responseObj.status + " and statusCode: " + responseObj.statusCode); if (responseObj.statusCode === "0" && that.compareVersion(responseObj.response, "1.0.0") >= 0) { console.log("Connection check successful, now continue with getPurchaseUrl API call..."); var request = "<Request name=\"" + AgoraLib.GET_PURCHASE_URL + "\" callerID=\"" + that.callerID + "\"><Parameters>"; request += "<Parameter name=\"BundleID\"><Value>" + that.bundleID + "</Value></Parameter>"; request += "<Parameter name=\"StraightToCheckout\"><Value>" + straightToCheckout + "</Value></Parameter>"; request += "</Parameters></Request>"; var sub_payload = String.format(AgoraLib.MESSAGE_REQUEST_TEMPLATE, request); var getPurchaseUrlVulcanMessage = new VulcanMessage(AgoraLib.MESSAGE_TYPE); getPurchaseUrlVulcanMessage.setPayload(sub_payload); VulcanInterface.addMessageListener(AgoraLib.RESPONSE_TYPE, that.responseCallback); VulcanInterface.dispatchMessage(getPurchaseUrlVulcanMessage); } else { var response = new AgoraLibResponse("", responseObj.status, responseObj.statusCode); callback(response); } }, ignoreACCC); // add a timeout and return error if response is not returned after a minute setTimeout(function(){ if (!success) { console.log("getPurchaseUrl: Request timed out"); var response = new AgoraLibResponse("", AgoraLib.status.internalClientError.status, AgoraLib.status.internalClientError.code); callback(response); } }, AgoraLib.TIMEOUT); }; /** * Creates an entitlement for this extension on Adobe Exchange for the signed in user. * If no user is available then the statusCode in the response will be 1004. * If the request is successful the statusCode in the response will be 0. * * By adding an entitlement the user will be kept up date with the latest version of the extension * which will be published to Adobe Exchange. * * This API has a dependency on VulcanInterface.js & CSInterface.js and will throw an error if either is not defined. * * @param callback The JavaScript handler function to return the AgoraLibResponse object. * @param ignoreACCC When true this API will not attempt to launch the Adobe Creative Cloud Connection application if it is not running. The default value is false. * @since 5.2.0 */ var createEntitlement = function(callback, ignoreACCC) { if (typeof(Vulcan) === 'undefined') { throw 'Vulcan.js is required.'; } if (typeof(CSInterface) === 'undefined') { throw 'CSInterface.js is required.'; } if (callback === null || callback === undefined) { callback = function(result){}; } if (ignoreACCC === null || ignoreACCC === undefined) { ignoreACCC = false; } this.createEntitlementCallback = callback; var that = this; var success = false; // check connection this.checkConnection(function(responseObj) { console.log("createEntitlement: checkConnection response: " + responseObj.response + " with status: " + responseObj.status + " and statusCode: " + responseObj.statusCode); success = true; // check status and statusCode for success. if (responseObj.statusCode === "0" && that.compareVersion(responseObj.response, "1.0.0") >= 0) { console.log("createEntitlement: Connection check successful, now continue with createEntitlement API call..."); var csLibrary = new CSInterface(); var extensionDir = csLibrary.getSystemPath(SystemPath.EXTENSION); var os = csLibrary.getOSInformation(); var pathSeparator = os.indexOf("Win") >= 0 ? "\\" : "/"; var manifestPath = extensionDir + pathSeparator + "CSXS" + pathSeparator + "manifest.xml"; var fileContents = window.cep.fs.readFile(manifestPath); var error = true; if (window.DOMParser) { var parser = new window.DOMParser(); try { var xmlDoc = parser.parseFromString(fileContents.data, "text/xml"); var extManifest = xmlDoc.getElementsByTagName("ExtensionManifest")[0]; if (extManifest) { var extensionBundleVersion = extManifest.attributes.getNamedItem("ExtensionBundleVersion").nodeValue; var request = "<Request name=\"" + AgoraLib.CREATE_ENTITLEMENT + "\" callerID=\"" + that.callerID + "\"><Parameters>"; request += "<Parameter name=\"BundleID\"><Value>" + that.bundleID + "</Value></Parameter>"; request += "<Parameter name=\"ExtensionBundleVersion\"><Value>" + extensionBundleVersion + "</Value></Parameter>"; request += "</Parameters></Request>"; var sub_payload = String.format(AgoraLib.MESSAGE_REQUEST_TEMPLATE, request); var createEntitlementVulcanMessage = new VulcanMessage(AgoraLib.MESSAGE_TYPE); createEntitlementVulcanMessage.setPayload(sub_payload); VulcanInterface.addMessageListener(AgoraLib.RESPONSE_TYPE, that.responseCallback); VulcanInterface.dispatchMessage(createEntitlementVulcanMessage); error = false; } } catch(e) { console.log("AgoraLibError: " + e); } } if (error) { var response1 = new AgoraLibResponse("", AgoraLib.status.internalClientError.status, AgoraLib.status.internalClientError.code); callback(response1); } } else { var response2 = new AgoraLibResponse("", responseObj.status, responseObj.statusCode); callback(response2); } }, ignoreACCC); // add a timeout and return error if response is not returned after a minute setTimeout(function(){ if (!success) { console.log("createEntitlement: Request timed out"); var response = new AgoraLibResponse("", AgoraLib.status.internalClientError.status, AgoraLib.status.internalClientError.code); callback(response); } }, AgoraLib.TIMEOUT); }; return { constructor: AgoraLib, isEntitled: isEntitled, getPurchaseUrl: getPurchaseUrl, createEntitlement: createEntitlement }; })(); /** * Provides consts for some of the status responses returned by the AgoraLib client. */ AgoraLib.status = { /* Success Responses */ success : { status : "Success", code : "0" }, // Create Entitlement success responses updateAvailable : { status : "Success. Update available", code : "1" }, entitlementAlreadyCreated : { status : "Success. Entitlement already created", code : "2" }, // IsEntitled success responses perpetualPurchase : { status : "Perpetual purchase", code : "1" }, trialPurchase : { status : "Trial purchase", code : "2" }, subscriptionPurchase : { status : "Subscription purchase", code : "3" }, free : { status : "Free", code : "4" }, /* end of Success Responses */ /* Error Responses */ // IsEntitled error responses userNotEntitledError : { status : "User not entitled or product not found", code : "-1" }, subscriptionExpiredError : { status : "Subscription expired", code : "-2" }, // General error responses networkDisabledError : { status : "Network disabled", code : "1001" }, networkError : { status : "Network error", code : "1002" }, productNotFoundError : { status : "Product not found", code : "1003" }, UserLoggedOutError : { status : "User logged out", code : "1004" }, internalClientError : { status : "Internal client error", code : "1005" }, internalServerError : { status : "Internal server error", code : "1006" }, creativeCloudFailedToLaunchError : { status : "Adobe Creative Cloud Desktop failed to launch", code : "1007" }, creativeCloudNotFoundError : { status : "Adobe Creative Cloud Desktop is not installed", code : "1008" }, ApiNotSupportedError : { status : "API not supported", code : "1009" }, creativeCloudNotLaunchedError : { status : "Creative Cloud was not launched", code : "1010" } }; /** * Returned as the response by all AgoraLib APIs. * @param string response The main result of the API request * @param string status Textual description that either provides information of an error or additional information about the response. * @param int statusCode status code. */ function AgoraLibResponse(response, status, statusCode) { this.response = response; this.status = status; this.statusCode = statusCode; } //--------------------------------------- AgoraLib Consts ------------------------------ // AgoraLib.IS_ENTITLED = "IsEntitled"; AgoraLib.GET_PURCHASE_URL = "GetPurchaseUrl"; AgoraLib.CREATE_ENTITLEMENT = "CreateEntitlement"; AgoraLib.GET_VERSION = "GetVersion"; AgoraLib.STATUS = "Status"; AgoraLib.STATUSCODE = "StatusCode"; AgoraLib.MESSAGE_TYPE = "vulcan.SuiteMessage.cosy.exchangeplugin.ApiRequest"; AgoraLib.RESPONSE_TYPE = "vulcan.SuiteMessage.cosy.exchangeplugin.ApiResponse"; AgoraLib.ACCC_STARTED_UP_MESSAGE = "vulcan.SuiteMessage.any.cosy.app.StartedUp"; AgoraLib.MESSAGE_REQUEST_TEMPLATE = "<Message><Requests>{0}</Requests></Message>"; AgoraLib.MESSAGE_RESPONSE_TEMPLATE = "<Message><Responses>{0}</Responses></Message>"; AgoraLib.TIMEOUT = 60000;