@@ -274,5 +357,7 @@
type="text/x-handlebars-template">
{{js "js/device-detail.js"}}
+ {{js "js/remote-session.js"}}
+ {{js "js/jquery.touchSwipe.min.js"}}
{{/if}}
{{/zone}}
diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/device-view.js b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/device-view.js
index 76b097605..da76ed24e 100644
--- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/device-view.js
+++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/device-view.js
@@ -22,6 +22,8 @@ function onRequest(context) {
var deviceId = request.getParameter("id");
var deviceViewData = {};
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
+ var carbonServer = require("carbon").server;
+ var constants = require("/app/modules/constants.js")
if (deviceType && deviceId) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
@@ -182,6 +184,23 @@ function onRequest(context) {
} else if (response["status"] == "notFound") {
deviceViewData["deviceFound"] = false;
}
+
+ var remoteSessionEndpoint = devicemgtProps["remoteSessionWSURL"].replace("https", "wss");
+ var jwtService = carbonServer.osgiService('org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService');
+ var jwtClient = jwtService.getJWTClient();
+ var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]);
+ var token = "";
+ if (encodedClientKeys) {
+ var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
+ var resp = tokenUtil.decode(encodedClientKeys).split(":");
+ var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
+ if (tokenPair) {
+ token = tokenPair.accessToken;
+ }
+ }
+ remoteSessionEndpoint = remoteSessionEndpoint + "/remote/session/clients/" + deviceType + "/" + deviceId +
+ "?websocketToken=" + token
+ deviceViewData["remoteSessionEndpoint"] = remoteSessionEndpoint;
} else {
deviceViewData["deviceFound"] = false;
}
diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/public/css/terminal.css b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/public/css/terminal.css
new file mode 100644
index 000000000..c6899148f
--- /dev/null
+++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/public/css/terminal.css
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+.terminal {
+ background-color: #1f1d1d;
+ border: 1px solid #000;
+ color: #39ef39;
+ padding: 8px;
+ font-family: courier new;
+}
diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/public/js/jquery.touchSwipe.min.js b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/public/js/jquery.touchSwipe.min.js
new file mode 100644
index 000000000..703634a25
--- /dev/null
+++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android.device-view/public/js/jquery.touchSwipe.min.js
@@ -0,0 +1,14 @@
+/*!
+ * @fileOverview TouchSwipe - jQuery Plugin
+ * @version 1.6.18
+ *
+ * @author Matt Bryson http://www.github.com/mattbryson
+ * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
+ * @see http://labs.rampinteractive.co.uk/touchSwipe/
+ * @see http://plugins.jquery.com/project/touchSwipe
+ * @license
+ * Copyright (c) 2010-2015 Matt Bryson
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ */
+!function(factory){"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],factory):factory("undefined"!=typeof module&&module.exports?require("jquery"):jQuery)}(function($){"use strict";function init(options){return!options||void 0!==options.allowPageScroll||void 0===options.swipe&&void 0===options.swipeStatus||(options.allowPageScroll=NONE),void 0!==options.click&&void 0===options.tap&&(options.tap=options.click),options||(options={}),options=$.extend({},$.fn.swipe.defaults,options),this.each(function(){var $this=$(this),plugin=$this.data(PLUGIN_NS);plugin||(plugin=new TouchSwipe(this,options),$this.data(PLUGIN_NS,plugin))})}function TouchSwipe(element,options){function touchStart(jqEvent){if(!(getTouchInProgress()||$(jqEvent.target).closest(options.excludedElements,$element).length>0)){var event=jqEvent.originalEvent?jqEvent.originalEvent:jqEvent;if(!event.pointerType||"mouse"!=event.pointerType||0!=options.fallbackToMouseEvents){var ret,touches=event.touches,evt=touches?touches[0]:event;return phase=PHASE_START,touches?fingerCount=touches.length:options.preventDefaultEvents!==!1&&jqEvent.preventDefault(),distance=0,direction=null,currentDirection=null,pinchDirection=null,duration=0,startTouchesDistance=0,endTouchesDistance=0,pinchZoom=1,pinchDistance=0,maximumsMap=createMaximumsData(),cancelMultiFingerRelease(),createFingerData(0,evt),!touches||fingerCount===options.fingers||options.fingers===ALL_FINGERS||hasPinches()?(startTime=getTimeStamp(),2==fingerCount&&(createFingerData(1,touches[1]),startTouchesDistance=endTouchesDistance=calculateTouchesDistance(fingerData[0].start,fingerData[1].start)),(options.swipeStatus||options.pinchStatus)&&(ret=triggerHandler(event,phase))):ret=!1,ret===!1?(phase=PHASE_CANCEL,triggerHandler(event,phase),ret):(options.hold&&(holdTimeout=setTimeout($.proxy(function(){$element.trigger("hold",[event.target]),options.hold&&(ret=options.hold.call($element,event,event.target))},this),options.longTapThreshold)),setTouchInProgress(!0),null)}}}function touchMove(jqEvent){var event=jqEvent.originalEvent?jqEvent.originalEvent:jqEvent;if(phase!==PHASE_END&&phase!==PHASE_CANCEL&&!inMultiFingerRelease()){var ret,touches=event.touches,evt=touches?touches[0]:event,currentFinger=updateFingerData(evt);if(endTime=getTimeStamp(),touches&&(fingerCount=touches.length),options.hold&&clearTimeout(holdTimeout),phase=PHASE_MOVE,2==fingerCount&&(0==startTouchesDistance?(createFingerData(1,touches[1]),startTouchesDistance=endTouchesDistance=calculateTouchesDistance(fingerData[0].start,fingerData[1].start)):(updateFingerData(touches[1]),endTouchesDistance=calculateTouchesDistance(fingerData[0].end,fingerData[1].end),pinchDirection=calculatePinchDirection(fingerData[0].end,fingerData[1].end)),pinchZoom=calculatePinchZoom(startTouchesDistance,endTouchesDistance),pinchDistance=Math.abs(startTouchesDistance-endTouchesDistance)),fingerCount===options.fingers||options.fingers===ALL_FINGERS||!touches||hasPinches()){if(direction=calculateDirection(currentFinger.start,currentFinger.end),currentDirection=calculateDirection(currentFinger.last,currentFinger.end),validateDefaultEvent(jqEvent,currentDirection),distance=calculateDistance(currentFinger.start,currentFinger.end),duration=calculateDuration(),setMaxDistance(direction,distance),ret=triggerHandler(event,phase),!options.triggerOnTouchEnd||options.triggerOnTouchLeave){var inBounds=!0;if(options.triggerOnTouchLeave){var bounds=getbounds(this);inBounds=isInBounds(currentFinger.end,bounds)}!options.triggerOnTouchEnd&&inBounds?phase=getNextPhase(PHASE_MOVE):options.triggerOnTouchLeave&&!inBounds&&(phase=getNextPhase(PHASE_END)),phase!=PHASE_CANCEL&&phase!=PHASE_END||triggerHandler(event,phase)}}else phase=PHASE_CANCEL,triggerHandler(event,phase);ret===!1&&(phase=PHASE_CANCEL,triggerHandler(event,phase))}}function touchEnd(jqEvent){var event=jqEvent.originalEvent?jqEvent.originalEvent:jqEvent,touches=event.touches;if(touches){if(touches.length&&!inMultiFingerRelease())return startMultiFingerRelease(event),!0;if(touches.length&&inMultiFingerRelease())return!0}return inMultiFingerRelease()&&(fingerCount=fingerCountAtRelease),endTime=getTimeStamp(),duration=calculateDuration(),didSwipeBackToCancel()||!validateSwipeDistance()?(phase=PHASE_CANCEL,triggerHandler(event,phase)):options.triggerOnTouchEnd||options.triggerOnTouchEnd===!1&&phase===PHASE_MOVE?(options.preventDefaultEvents!==!1&&jqEvent.preventDefault(),phase=PHASE_END,triggerHandler(event,phase)):!options.triggerOnTouchEnd&&hasTap()?(phase=PHASE_END,triggerHandlerForGesture(event,phase,TAP)):phase===PHASE_MOVE&&(phase=PHASE_CANCEL,triggerHandler(event,phase)),setTouchInProgress(!1),null}function touchCancel(){fingerCount=0,endTime=0,startTime=0,startTouchesDistance=0,endTouchesDistance=0,pinchZoom=1,cancelMultiFingerRelease(),setTouchInProgress(!1)}function touchLeave(jqEvent){var event=jqEvent.originalEvent?jqEvent.originalEvent:jqEvent;options.triggerOnTouchLeave&&(phase=getNextPhase(PHASE_END),triggerHandler(event,phase))}function removeListeners(){$element.unbind(START_EV,touchStart),$element.unbind(CANCEL_EV,touchCancel),$element.unbind(MOVE_EV,touchMove),$element.unbind(END_EV,touchEnd),LEAVE_EV&&$element.unbind(LEAVE_EV,touchLeave),setTouchInProgress(!1)}function getNextPhase(currentPhase){var nextPhase=currentPhase,validTime=validateSwipeTime(),validDistance=validateSwipeDistance(),didCancel=didSwipeBackToCancel();return!validTime||didCancel?nextPhase=PHASE_CANCEL:!validDistance||currentPhase!=PHASE_MOVE||options.triggerOnTouchEnd&&!options.triggerOnTouchLeave?!validDistance&¤tPhase==PHASE_END&&options.triggerOnTouchLeave&&(nextPhase=PHASE_CANCEL):nextPhase=PHASE_END,nextPhase}function triggerHandler(event,phase){var ret,touches=event.touches;return(didSwipe()||hasSwipes())&&(ret=triggerHandlerForGesture(event,phase,SWIPE)),(didPinch()||hasPinches())&&ret!==!1&&(ret=triggerHandlerForGesture(event,phase,PINCH)),didDoubleTap()&&ret!==!1?ret=triggerHandlerForGesture(event,phase,DOUBLE_TAP):didLongTap()&&ret!==!1?ret=triggerHandlerForGesture(event,phase,LONG_TAP):didTap()&&ret!==!1&&(ret=triggerHandlerForGesture(event,phase,TAP)),phase===PHASE_CANCEL&&touchCancel(event),phase===PHASE_END&&(touches?touches.length||touchCancel(event):touchCancel(event)),ret}function triggerHandlerForGesture(event,phase,gesture){var ret;if(gesture==SWIPE){if($element.trigger("swipeStatus",[phase,direction||null,distance||0,duration||0,fingerCount,fingerData,currentDirection]),options.swipeStatus&&(ret=options.swipeStatus.call($element,event,phase,direction||null,distance||0,duration||0,fingerCount,fingerData,currentDirection),ret===!1))return!1;if(phase==PHASE_END&&validateSwipe()){if(clearTimeout(singleTapTimeout),clearTimeout(holdTimeout),$element.trigger("swipe",[direction,distance,duration,fingerCount,fingerData,currentDirection]),options.swipe&&(ret=options.swipe.call($element,event,direction,distance,duration,fingerCount,fingerData,currentDirection),ret===!1))return!1;switch(direction){case LEFT:$element.trigger("swipeLeft",[direction,distance,duration,fingerCount,fingerData,currentDirection]),options.swipeLeft&&(ret=options.swipeLeft.call($element,event,direction,distance,duration,fingerCount,fingerData,currentDirection));break;case RIGHT:$element.trigger("swipeRight",[direction,distance,duration,fingerCount,fingerData,currentDirection]),options.swipeRight&&(ret=options.swipeRight.call($element,event,direction,distance,duration,fingerCount,fingerData,currentDirection));break;case UP:$element.trigger("swipeUp",[direction,distance,duration,fingerCount,fingerData,currentDirection]),options.swipeUp&&(ret=options.swipeUp.call($element,event,direction,distance,duration,fingerCount,fingerData,currentDirection));break;case DOWN:$element.trigger("swipeDown",[direction,distance,duration,fingerCount,fingerData,currentDirection]),options.swipeDown&&(ret=options.swipeDown.call($element,event,direction,distance,duration,fingerCount,fingerData,currentDirection))}}}if(gesture==PINCH){if($element.trigger("pinchStatus",[phase,pinchDirection||null,pinchDistance||0,duration||0,fingerCount,pinchZoom,fingerData]),options.pinchStatus&&(ret=options.pinchStatus.call($element,event,phase,pinchDirection||null,pinchDistance||0,duration||0,fingerCount,pinchZoom,fingerData),ret===!1))return!1;if(phase==PHASE_END&&validatePinch())switch(pinchDirection){case IN:$element.trigger("pinchIn",[pinchDirection||null,pinchDistance||0,duration||0,fingerCount,pinchZoom,fingerData]),options.pinchIn&&(ret=options.pinchIn.call($element,event,pinchDirection||null,pinchDistance||0,duration||0,fingerCount,pinchZoom,fingerData));break;case OUT:$element.trigger("pinchOut",[pinchDirection||null,pinchDistance||0,duration||0,fingerCount,pinchZoom,fingerData]),options.pinchOut&&(ret=options.pinchOut.call($element,event,pinchDirection||null,pinchDistance||0,duration||0,fingerCount,pinchZoom,fingerData))}}return gesture==TAP?phase!==PHASE_CANCEL&&phase!==PHASE_END||(clearTimeout(singleTapTimeout),clearTimeout(holdTimeout),hasDoubleTap()&&!inDoubleTap()?(doubleTapStartTime=getTimeStamp(),singleTapTimeout=setTimeout($.proxy(function(){doubleTapStartTime=null,$element.trigger("tap",[event.target]),options.tap&&(ret=options.tap.call($element,event,event.target))},this),options.doubleTapThreshold)):(doubleTapStartTime=null,$element.trigger("tap",[event.target]),options.tap&&(ret=options.tap.call($element,event,event.target)))):gesture==DOUBLE_TAP?phase!==PHASE_CANCEL&&phase!==PHASE_END||(clearTimeout(singleTapTimeout),clearTimeout(holdTimeout),doubleTapStartTime=null,$element.trigger("doubletap",[event.target]),options.doubleTap&&(ret=options.doubleTap.call($element,event,event.target))):gesture==LONG_TAP&&(phase!==PHASE_CANCEL&&phase!==PHASE_END||(clearTimeout(singleTapTimeout),doubleTapStartTime=null,$element.trigger("longtap",[event.target]),options.longTap&&(ret=options.longTap.call($element,event,event.target)))),ret}function validateSwipeDistance(){var valid=!0;return null!==options.threshold&&(valid=distance>=options.threshold),valid}function didSwipeBackToCancel(){var cancelled=!1;return null!==options.cancelThreshold&&null!==direction&&(cancelled=getMaxDistance(direction)-distance>=options.cancelThreshold),cancelled}function validatePinchDistance(){return null!==options.pinchThreshold?pinchDistance>=options.pinchThreshold:!0}function validateSwipeTime(){var result;return result=options.maxTimeThreshold?!(duration>=options.maxTimeThreshold):!0}function validateDefaultEvent(jqEvent,direction){if(options.preventDefaultEvents!==!1)if(options.allowPageScroll===NONE)jqEvent.preventDefault();else{var auto=options.allowPageScroll===AUTO;switch(direction){case LEFT:(options.swipeLeft&&auto||!auto&&options.allowPageScroll!=HORIZONTAL)&&jqEvent.preventDefault();break;case RIGHT:(options.swipeRight&&auto||!auto&&options.allowPageScroll!=HORIZONTAL)&&jqEvent.preventDefault();break;case UP:(options.swipeUp&&auto||!auto&&options.allowPageScroll!=VERTICAL)&&jqEvent.preventDefault();break;case DOWN:(options.swipeDown&&auto||!auto&&options.allowPageScroll!=VERTICAL)&&jqEvent.preventDefault();break;case NONE:}}}function validatePinch(){var hasCorrectFingerCount=validateFingers(),hasEndPoint=validateEndPoint(),hasCorrectDistance=validatePinchDistance();return hasCorrectFingerCount&&hasEndPoint&&hasCorrectDistance}function hasPinches(){return!!(options.pinchStatus||options.pinchIn||options.pinchOut)}function didPinch(){return!(!validatePinch()||!hasPinches())}function validateSwipe(){var hasValidTime=validateSwipeTime(),hasValidDistance=validateSwipeDistance(),hasCorrectFingerCount=validateFingers(),hasEndPoint=validateEndPoint(),didCancel=didSwipeBackToCancel(),valid=!didCancel&&hasEndPoint&&hasCorrectFingerCount&&hasValidDistance&&hasValidTime;return valid}function hasSwipes(){return!!(options.swipe||options.swipeStatus||options.swipeLeft||options.swipeRight||options.swipeUp||options.swipeDown)}function didSwipe(){return!(!validateSwipe()||!hasSwipes())}function validateFingers(){return fingerCount===options.fingers||options.fingers===ALL_FINGERS||!SUPPORTS_TOUCH}function validateEndPoint(){return 0!==fingerData[0].end.x}function hasTap(){return!!options.tap}function hasDoubleTap(){return!!options.doubleTap}function hasLongTap(){return!!options.longTap}function validateDoubleTap(){if(null==doubleTapStartTime)return!1;var now=getTimeStamp();return hasDoubleTap()&&now-doubleTapStartTime<=options.doubleTapThreshold}function inDoubleTap(){return validateDoubleTap()}function validateTap(){return(1===fingerCount||!SUPPORTS_TOUCH)&&(isNaN(distance)||distance
options.longTapThreshold&&DOUBLE_TAP_THRESHOLD>distance}function didTap(){return!(!validateTap()||!hasTap())}function didDoubleTap(){return!(!validateDoubleTap()||!hasDoubleTap())}function didLongTap(){return!(!validateLongTap()||!hasLongTap())}function startMultiFingerRelease(event){previousTouchEndTime=getTimeStamp(),fingerCountAtRelease=event.touches.length+1}function cancelMultiFingerRelease(){previousTouchEndTime=0,fingerCountAtRelease=0}function inMultiFingerRelease(){var withinThreshold=!1;if(previousTouchEndTime){var diff=getTimeStamp()-previousTouchEndTime;diff<=options.fingerReleaseThreshold&&(withinThreshold=!0)}return withinThreshold}function getTouchInProgress(){return!($element.data(PLUGIN_NS+"_intouch")!==!0)}function setTouchInProgress(val){$element&&(val===!0?($element.bind(MOVE_EV,touchMove),$element.bind(END_EV,touchEnd),LEAVE_EV&&$element.bind(LEAVE_EV,touchLeave)):($element.unbind(MOVE_EV,touchMove,!1),$element.unbind(END_EV,touchEnd,!1),LEAVE_EV&&$element.unbind(LEAVE_EV,touchLeave,!1)),$element.data(PLUGIN_NS+"_intouch",val===!0))}function createFingerData(id,evt){var f={start:{x:0,y:0},last:{x:0,y:0},end:{x:0,y:0}};return f.start.x=f.last.x=f.end.x=evt.pageX||evt.clientX,f.start.y=f.last.y=f.end.y=evt.pageY||evt.clientY,fingerData[id]=f,f}function updateFingerData(evt){var id=void 0!==evt.identifier?evt.identifier:0,f=getFingerData(id);return null===f&&(f=createFingerData(id,evt)),f.last.x=f.end.x,f.last.y=f.end.y,f.end.x=evt.pageX||evt.clientX,f.end.y=evt.pageY||evt.clientY,f}function getFingerData(id){return fingerData[id]||null}function setMaxDistance(direction,distance){direction!=NONE&&(distance=Math.max(distance,getMaxDistance(direction)),maximumsMap[direction].distance=distance)}function getMaxDistance(direction){return maximumsMap[direction]?maximumsMap[direction].distance:void 0}function createMaximumsData(){var maxData={};return maxData[LEFT]=createMaximumVO(LEFT),maxData[RIGHT]=createMaximumVO(RIGHT),maxData[UP]=createMaximumVO(UP),maxData[DOWN]=createMaximumVO(DOWN),maxData}function createMaximumVO(dir){return{direction:dir,distance:0}}function calculateDuration(){return endTime-startTime}function calculateTouchesDistance(startPoint,endPoint){var diffX=Math.abs(startPoint.x-endPoint.x),diffY=Math.abs(startPoint.y-endPoint.y);return Math.round(Math.sqrt(diffX*diffX+diffY*diffY))}function calculatePinchZoom(startDistance,endDistance){var percent=endDistance/startDistance*1;return percent.toFixed(2)}function calculatePinchDirection(){return 1>pinchZoom?OUT:IN}function calculateDistance(startPoint,endPoint){return Math.round(Math.sqrt(Math.pow(endPoint.x-startPoint.x,2)+Math.pow(endPoint.y-startPoint.y,2)))}function calculateAngle(startPoint,endPoint){var x=startPoint.x-endPoint.x,y=endPoint.y-startPoint.y,r=Math.atan2(y,x),angle=Math.round(180*r/Math.PI);return 0>angle&&(angle=360-Math.abs(angle)),angle}function calculateDirection(startPoint,endPoint){if(comparePoints(startPoint,endPoint))return NONE;var angle=calculateAngle(startPoint,endPoint);return 45>=angle&&angle>=0?LEFT:360>=angle&&angle>=315?LEFT:angle>=135&&225>=angle?RIGHT:angle>45&&135>angle?DOWN:UP}function getTimeStamp(){var now=new Date;return now.getTime()}function getbounds(el){el=$(el);var offset=el.offset(),bounds={left:offset.left,right:offset.left+el.outerWidth(),top:offset.top,bottom:offset.top+el.outerHeight()};return bounds}function isInBounds(point,bounds){return point.x>bounds.left&&point.xbounds.top&&point.y' + rs_WebSocketURL + '', type: 'error'});
+ rs_websocket.close();
+ location.reload();
+};
+
+$("#btn-connect-device").click(function() {
+
+ $('#loading-remote-session').removeClass('hidden');
+ $('#btn-connect-device').addClass('hidden');
+ $('#lbl-remote-session-status').text('Connecting to Server...');
+ initializeRemoteSession();
+});
+
+
+$("#btn-close-remote-session").click(function() {
+ // Close the WebSocket.
+ rs_websocket.close();
+ rs_websocket.set_closed();
+ $('#btn-connect-device').removeClass('hidden');
+ $('#remote-session-operations').addClass('hidden');
+ $('#btn-close-remote-session').addClass('hidden');
+ $('#loading-screen').addClass('hidden');
+ $('#btn-stop-screen').addClass('hidden');
+ $('#btn-start-screen').removeClass('hidden');
+ location.reload();
+});
+
+$("#btn-refresh-logCat").click(function() {
+
+ $('#loading-logcat').removeClass('hidden');
+ $('#btn-refresh-logCat').addClass('hidden');
+ var message = new Object();
+ message.code ="REMOTE_LOGCAT";
+
+ // Send the message through the WebSocket.
+ rs_websocket.send(JSON.stringify(message));
+
+ // Clear out the message field.
+ $("#logcat-response").val("") ;
+
+});
+
+
+function initializeRemoteSessionWebSocket() {
+
+ rs_websocket = new WebSocket(rs_WebSocketURL);
+ rs_websocket.onopen = remoteSessionWebSocketOnOpen;
+ rs_websocket.onmessage = remoteSessionWebSocketOnMessage;
+ rs_websocket.onclose = remoteSessionWebSocketOnClose;
+ rs_websocket.onerror = remoteSessionWebSocketOnError;
+
+}
+
+function initializeRemoteSession() {
+
+ rs_WebSocketURL = $("#remote-session").data("remote-session-uri");
+ if(rs_WebSocketURL != null) {
+ initializeRemoteSessionWebSocket();
+ window.onbeforeunload = function () {
+ rs_websocket.close();
+ }
+ $('#lbl-remote-session-status').text('Waiting on device to connect...');
+
+ } else {
+ noty({text: 'Remote Session endpoint connection Failed!', type: 'error'});
+ $('#btn-connect-device').removeClass('hidden');
+ $('#loading-remote-session').addClass('hidden');
+ }
+}
+
+
+$("#shell-command").keyup(function(event){
+ if(event.keyCode == 13){
+ var message = new Object();
+ message.code ="REMOTE_SHELL";
+ message.payload = $("#shell-command").val();
+
+
+ // Send the message through the WebSocket.
+ rs_websocket.send(JSON.stringify(message));
+
+ // Clear out the message field.
+ $("#shell-command").val("") ;
+ $("#shell-response").val("") ;
+ $('#loading-terminal').removeClass('hidden');
+ }
+});
+
+
+$("#btn-start-screen").click(function() {
+
+
+ $('#loading-screen').removeClass('hidden');
+ $('#btn-start-screen').addClass('hidden');
+ $('#remote-control-pannel').removeClass('hidden');
+ $('#btn-stop-screen').removeClass('hidden');
+ var message = new Object();
+ message.code ="REMOTE_SCREEN";
+ message.payload = "start";
+ // Send the message through the WebSocket.
+ rs_websocket.send(JSON.stringify(message));
+});
+
+
+$("#btn-stop-screen").click(function() {
+
+ var canvas = document.getElementById("canvas");
+ var ctx = canvas.getContext('2d');
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ $('#loading-screen').addClass('hidden');
+ $('#remote-control-pannel').addClass('hidden');
+ $('#btn-stop-screen').addClass('hidden');
+ $('#btn-start-screen').removeClass('hidden');
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ var message = new Object();
+ message.code ="REMOTE_SCREEN";
+ message.payload = "stop";
+ // Send the message through the WebSocket.
+ rs_websocket.send(JSON.stringify(message));
+});
+
+
+$(function() {
+ //Enable swiping...
+ $("#canvas").swipe({
+ //Generic swipe handler for all directions
+ swipe: function(event, direction, distance, duration, fingerCount, fingerData) {
+ switch (direction) {
+ case "right":
+ $("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " RIGHT", 10, 90)
+ break;
+ case "left":
+ $("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " LEFT", 10, 90)
+ break;
+ case "up":
+ $("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " UP", 10, 90)
+ break;
+ case "down":
+ $("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " DOWN", 10, 90)
+ break;
+ default:
+ $("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY, 10, 90)
+ break;
+ }
+ },
+
+ //Default is 75px, set to 0 for demo so any distance triggers swipe
+ threshold: 0
+ });
+});
diff --git a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml
new file mode 100644
index 000000000..44abb0494
--- /dev/null
+++ b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml
@@ -0,0 +1,134 @@
+
+
+
+ org.wso2.carbon.devicemgt-plugins
+ extensions-feature
+ 4.0.35-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+
+ org.wso2.carbon.device.mgt.remote.session.feature
+ pom
+ 4.0.35-SNAPSHOT
+ WSO2 Carbon - Remote Session Manager
+ http://wso2.org
+ This feature contains the core bundles required iot Remote Sessions
+
+
+
+ org.wso2.carbon.devicemgt-plugins
+ org.wso2.carbon.device.mgt.extensions.remote.session
+
+
+ io.github.openfeign
+ feign-jaxrs
+ ${io.github.openfeign.version}
+
+
+ io.github.openfeign
+ feign-gson
+ ${io.github.openfeign.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy
+ package
+
+ copy
+
+
+
+
+ org.wso2.carbon.devicemgt-plugins
+ org.wso2.carbon.device.mgt.extensions.remote.session.endpoint
+ ${carbon.devicemgt.plugins.version}
+ war
+ true
+
+ ${project.build.directory}/maven-shared-archive-resources/webapps/
+
+ remote-session.war
+
+
+
+
+
+
+
+ maven-resources-plugin
+
+
+ copy-resources
+ generate-resources
+
+ copy-resources
+
+
+ src/main/resources
+
+
+ resources
+
+ build.properties
+ p2.inf
+
+
+
+
+
+
+
+
+ org.wso2.maven
+ carbon-p2-plugin
+ ${carbon.p2.plugin.version}
+
+
+ p2-feature-generation
+ package
+
+ p2-feature-gen
+
+
+ org.wso2.carbon.device.mgt.remote.session
+ ../../../features/etc/feature.properties
+
+
+ org.wso2.carbon.p2.category.type:server
+ org.eclipse.equinox.p2.type.group:true
+
+
+
+
+ org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.extensions.remote.session:${carbon.devicemgt.plugins.version}
+
+
+
+ org.wso2.carbon.identity.inbound.auth.oauth2:org.wso2.carbon.identity.oauth.stub:${identity.inbound.auth.oauth.version}
+
+
+ io.github.openfeign:feign-core:${io.github.openfeign.version}
+
+
+ io.github.openfeign:feign-slf4j:${io.github.openfeign.version}
+
+
+ io.github.openfeign:feign-gson:${io.github.openfeign.version}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/src/main/resources/build.properties b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/src/main/resources/build.properties
new file mode 100644
index 000000000..33bb0980d
--- /dev/null
+++ b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/src/main/resources/build.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+#
+# WSO2 Inc. licenses this file to you under the Apache License,
+# Version 2.0 (the "License"); you may not use this file except
+# in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+custom = true
diff --git a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/src/main/resources/p2.inf b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/src/main/resources/p2.inf
new file mode 100644
index 000000000..9efb7a994
--- /dev/null
+++ b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/src/main/resources/p2.inf
@@ -0,0 +1,3 @@
+instructions.configure = \
+org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
+org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.remote.session_${feature.version}/webapps/,target:${installFolder}/../../deployment/server/webapps/,overwrite:true);\
\ No newline at end of file