"use strict"; var __extends = this.__extends || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __(); }; var CloudExperienceHost; (function (CloudExperienceHost) { var Channel; (function (Channel) { Channel.MessageType = { invoke: 'invoke', event: 'event', callback: 'callback' }; var Message = (function () { function Message(t) { this.type = t; this.value = new Object; } return Message; })(); Channel.Message = Message; var EventMsg = (function (_super) { __extends(EventMsg, _super); function EventMsg() { _super.call(this, Channel.MessageType.event); } return EventMsg; })(Message); Channel.EventMsg = EventMsg; var InvokeMsg = (function (_super) { __extends(InvokeMsg, _super); function InvokeMsg() { _super.call(this, Channel.MessageType.invoke); } return InvokeMsg; })(Message); Channel.InvokeMsg = InvokeMsg; var CallbackMsg = (function (_super) { __extends(CallbackMsg, _super); function CallbackMsg() { _super.call(this, Channel.MessageType.callback); } return CallbackMsg; })(Message); Channel.CallbackMsg = CallbackMsg; function createInvokeMsg(funcName, args, context) { var msg = new InvokeMsg(); msg.value.name = funcName; msg.value.args = args; msg.value.context = context; return msg; } Channel.createInvokeMsg = createInvokeMsg; function createEventMsg(eventName, data) { var msg = new EventMsg(); msg.value.name = eventName; if (data) { msg.value.data = data; } return msg; } Channel.createEventMsg = createEventMsg; function createCallbackMsg(context, funcName, result, iserror) { var msg = new CallbackMsg(); msg.value.context = context; msg.value.result = (funcName === 'WinJS.xhr') ? { 'response': result.response, 'status': result.status } : result; msg.value.iserror = iserror; return msg; } Channel.createCallbackMsg = createCallbackMsg; function stringify(msg) { return JSON.stringify(msg); } Channel.stringify = stringify; function parse(msg) { var m = JSON.parse(msg); return m; } Channel.parse = parse; })(Channel || (Channel = {})); var ContractHandler = (function () { function ContractHandler(rules) { this._rules = rules; } ContractHandler.prototype.invokeFromString = function (callerUri, method, args) { try { this._checkIfPermissionAllowed(callerUri, method); return WinJS.Promise.as(this._executeFunctionByName(method, args)); } catch (e) { return new WinJS.Promise(function (completeDispatch, errorDispatch ) { errorDispatch(e); }); } }; ContractHandler.prototype._checkIfPermissionAllowed = function (callerUri, method) { var trimmedCallerUri = this._trimUri(callerUri); var isAllowed = false; var namespaces = method.split("."); for (var fn = ""; !isAllowed && namespaces.length > 0; namespaces.pop()) { var ns = namespaces.join('.') + fn; if (this._rules.hasOwnProperty(ns)) { isAllowed = this._isAllowed(trimmedCallerUri, this._rules[ns]); } fn = ".*"; } if (isAllowed === false) { CloudExperienceHost.Telemetry.WebAppTelemetry.getInstance().logEvent("NotAuthorizedApiAccess", JSON.stringify({ 'callerUri': callerUri, 'trimmedCallerUri': trimmedCallerUri, 'method': method, 'isAllowed': isAllowed })); throw new Error("Application not authorized to access the API"); } }; ContractHandler.prototype._isAllowed = function (callerUri, allowedURIs) { var isAllowed = false; allowedURIs.forEach(function (uri) { if (uri === "*" || callerUri.toLowerCase() === uri.toLowerCase()) { isAllowed = true; } else if (uri.lastIndexOf('*') === (uri.length - 1)) { if (callerUri.toLowerCase().indexOf(uri.substr(0, uri.length - 1).toLowerCase(), 0) === 0) { isAllowed = true; } } }); return isAllowed; }; ContractHandler.prototype._trimUri = function (callerUri) { return callerUri.replace(/\/[^\/]+$/, "/"); }; ContractHandler.prototype._executeFunctionByName = function (functionName, args) { var context = window; var namespaces = functionName.split("."); var func = namespaces.pop(); for (var i = 0; i < namespaces.length; i++) { context = context[namespaces[i]]; } return context[func].apply(context, args); }; return ContractHandler; })(); CloudExperienceHost.ContractHandler = ContractHandler; var CallbackContext = (function () { function CallbackContext(completeDispatch, errorDispatch) { this._completeDispatch = completeDispatch; this._errorDispatch = errorDispatch; } CallbackContext.prototype.complete = function (result) { this._completeDispatch(result); }; CallbackContext.prototype.error = function (e) { this._errorDispatch(e); }; return CallbackContext; })(); var Bridge = (function () { function Bridge(target, contractHandler) { this._target = null; this._contractHandler = null; this._listeners = null; this._callbackContext = null; this._listeners = new Object(); this._callbackContext = new Object(); if (target) { this._target = target; } if (contractHandler) { this._contractHandler = contractHandler; } this._initializeTarget(); } Bridge.prototype._initializeTarget = function () { if (this._target) { this._target.addEventListener("MSWebViewScriptNotify", function (e) { this._dispatchMessage(e.value); }.bind(this)); } else { window["CloudExperienceHost.Bridge.dispatchMessage"] = function (e) { this._dispatchMessage(e); }.bind(this); } }; Bridge.prototype._postMessage = function (msg) { if (this._target && this._target["invokeScriptAsync"]) { this._target["invokeScriptAsync"]("CloudExperienceHost.Bridge.dispatchMessage", msg).start(); } else { window.external['notify'](msg); } }; Bridge.prototype._invokeLocal = function (m) { this._contractHandler.invokeFromString(this._target.src, m.value.name, m.value.args).done(function (result) { if (m.value.context) { this._callback(m, result, false); } }.bind(this), function (e) { if (m.value.context) { this._callback(m, e, true); } }.bind(this)); }; Bridge.prototype._receivedEvent = function (e) { if (this._contractHandler && this._contractHandler._rules && this._contractHandler._rules.hasOwnProperty(e.value.name)) { this._contractHandler._checkIfPermissionAllowed(this._target.src, e.value.name); } var listeners = this._listeners[e.value.name]; if (listeners) { listeners.map(function (listener) { listener.call(this, e.value.data); }.bind(this)); } }; Bridge.prototype._receivedResult = function (m) { var callback = this._callbackContext[m.value.context]; if (callback) { if (m.value.iserror) { callback.error(m.value.result); } else { callback.complete(m.value.result); } this._callbackContext[m.value.context] = null; delete this._callbackContext[m.value.context]; } }; Bridge.prototype._dispatchMessage = function (message) { var msg = Channel.parse(message); if (msg.type == Channel.MessageType.invoke) { this._invokeLocal(msg); } else if (msg.type == Channel.MessageType.event) { this._receivedEvent(msg); } else if (msg.type == Channel.MessageType.callback) { this._receivedResult(msg); } }; Bridge.prototype._callback = function (m, result, iserror) { if (iserror && !!result && (typeof result.number === 'number')) { Object.defineProperty(result, 'number', {enumerable: true}) } var msg = Channel.createCallbackMsg(m.value.context, m.value.name, result, iserror); this._postMessage(Channel.stringify(msg)); }; Bridge.prototype.invoke = function (funcName ) { var args = Array.prototype.slice.call(arguments).splice(1); return new WinJS.Promise(function (completeDispatch, errorDispatch ) { var uniqueid = Math.random().toString(16).slice(2); var context = funcName + '_' + uniqueid; this._callbackContext[context] = new CallbackContext(completeDispatch, errorDispatch); var msg = Channel.createInvokeMsg(funcName, args, context); this._postMessage(Channel.stringify(msg)); }.bind(this)); }; Bridge.prototype.fireEvent = function (eventName, data) { var msg = Channel.createEventMsg(eventName, data); this._postMessage(Channel.stringify(msg)); }; Bridge.prototype.addEventListener = function (eventName, listener) { if (!this._listeners.hasOwnProperty(eventName)) { this._listeners[eventName] = new Array(); } this._listeners[eventName].push(listener); }; return Bridge; })(); CloudExperienceHost.Bridge = Bridge; })(CloudExperienceHost || (CloudExperienceHost = {}));