1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2009, 2010, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2009, 2010, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 */ 27 28 /** 29 * Creates the mobile devices controller. 30 * @constructor 31 * @class 32 * This class represents the mobile devices controller. This controller manages the 33 * mobile devices page, which has a button toolbar and a list view of the devices. 34 * 35 * @author Parag Shah 36 * 37 * @param {DwtShell} container the shell 38 * @param {ZmPreferencesApp} prefsApp the preferences app 39 * @param {ZmPrefView} prefsView the preferences view 40 * 41 * @extends ZmController 42 */ 43 ZmMobileDevicesController = function(container, prefsApp, prefsView) { 44 45 ZmController.call(this, container, prefsApp); 46 47 this._prefsView = prefsView; 48 49 this._devices = new AjxVector(); 50 }; 51 52 ZmMobileDevicesController.prototype = new ZmController(); 53 ZmMobileDevicesController.prototype.constructor = ZmMobileDevicesController; 54 55 ZmMobileDevicesController.prototype.toString = 56 function() { 57 return "ZmMobileDevicesController"; 58 }; 59 60 /** 61 * Initializes the controller. 62 * 63 * @param {ZmToolBar} toolbar the toolbar 64 * @param {ZmListView} listView the list view 65 */ 66 ZmMobileDevicesController.prototype.initialize = 67 function(toolbar, listView) { 68 // init toolbar 69 this._toolbar = toolbar; 70 var buttons = this.getToolbarButtons(); 71 var tbListener = new AjxListener(this, this._toolbarListener); 72 for (var i = 0; i < buttons.length; i++) { 73 toolbar.addSelectionListener(buttons[i], tbListener); 74 } 75 this._resetOperations(toolbar, 0); 76 77 // init list view 78 this._listView = listView; 79 listView.addSelectionListener(new AjxListener(this, this._listSelectionListener)); 80 }; 81 82 ZmMobileDevicesController.prototype.initializeOAuthAppListView = 83 function(oAuthAppsListView) { 84 this._oAuthAppsListView = oAuthAppsListView; 85 }; 86 87 ZmMobileDevicesController.prototype.getToolbarButtons = 88 function() { 89 return [ 90 ZmOperation.MOBILE_REMOVE, 91 ZmOperation.SEP, 92 ZmOperation.MOBILE_SUSPEND_SYNC, 93 ZmOperation.MOBILE_RESUME_SYNC, 94 ZmOperation.SEP, 95 ZmOperation.MOBILE_WIPE 96 ]; 97 }; 98 99 ZmMobileDevicesController.prototype.loadDeviceInfo = 100 function() { 101 var soapDoc = AjxSoapDoc.create("GetDeviceStatusRequest", "urn:zimbraSync"); 102 var respCallback = new AjxCallback(this, this._handleResponseLoadDevices); 103 appCtxt.getAppController().sendRequest({soapDoc:soapDoc, asyncMode:true, callback:respCallback}); 104 }; 105 106 ZmMobileDevicesController.prototype._handleResponseLoadDevices = 107 function(results) { 108 // clean up 109 this._devices.removeAll(); 110 this._devices = new AjxVector(); 111 112 var list = results.getResponse().GetDeviceStatusResponse.device; 113 if (list && list.length) { 114 for (var i = 0; i < list.length; i++) { 115 this._devices.add(new ZmMobileDevice(list[i])); 116 } 117 } 118 119 this._listView.set(this._devices); 120 this._resetOperations(this._toolbar); 121 }; 122 123 ZmMobileDevicesController.prototype.loadOAuthConsumerAppInfo = 124 function() { 125 var jsonObj = { GetOAuthConsumersRequest : { _jsns:"urn:zimbraAccount"}}; 126 var callback = this._handleResponseLoadOAuthConsumer.bind(this); 127 appCtxt.getRequestMgr().sendRequest({jsonObj:jsonObj, asyncMode:true, callback:callback}); 128 }; 129 130 ZmMobileDevicesController.prototype._handleResponseLoadOAuthConsumer = 131 function(result){ 132 if (this._oAuthConsumerApps) { 133 this._oAuthConsumerApps.removeAll(); 134 } 135 this._oAuthConsumerApps = new AjxVector(); 136 137 var response = result.getResponse(); 138 var OAuthConsumersResponse = response.GetOAuthConsumersResponse; 139 var list = OAuthConsumersResponse.OAuthConsumer; 140 if (list && list.length) { 141 for (var i = 0; i < list.length; i++) { 142 this._oAuthConsumerApps.add(new ZmOAuthConsumerApp(list[i])); 143 } 144 } 145 this._oAuthAppsListView.set(this._oAuthConsumerApps); 146 }; 147 148 /** 149 * Handles left-clicking on a rule. Double click opens up a rule for editing. 150 * 151 * @param {DwtEvent} ev the click event 152 * 153 * @private 154 */ 155 ZmMobileDevicesController.prototype._listSelectionListener = 156 function(ev) { 157 if (ev.detail == DwtListView.ITEM_DBL_CLICKED) { 158 var device = this._listView.getSelection()[0]; 159 this._showMoreDetails(device); 160 } else { 161 this._resetOperations(this._toolbar, 1); 162 } 163 }; 164 165 ZmMobileDevicesController.prototype._showMoreDetails = 166 function(device) { 167 var msg = AjxTemplate.expand("prefs.Pages#MobileDeviceInfo", {device:device}); 168 var dlg = appCtxt.getMsgDialog(); 169 dlg.setMessage(msg); 170 dlg.popup(); 171 }; 172 173 174 // Listeners 175 176 ZmMobileDevicesController.prototype._toolbarListener = 177 function(ev) { 178 var item = this._listView.getSelection()[0]; 179 var id = ev.item.getData(ZmOperation.KEY_ID); 180 var callback = new AjxCallback(this, this._handleAction, [item, id]); 181 var action = ev.item.getData(ZmOperation.KEY_ID); 182 183 if (action == ZmOperation.MOBILE_WIPE) { 184 // if the item status is wipe-requested, then, user wants to cancel 185 if (item.status == ZmMobileDevice.STATUS_REMOTE_WIPE_REQUESTED) { 186 action = ZmOperation.MOBILE_CANCEL_WIPE; 187 } else { 188 // bug 42135: add confirmation for mobile wipe 189 var dialog = appCtxt.getOkCancelMsgDialog(); 190 dialog.setMessage(ZmMsg.mobileDeviceWipeConfirm); 191 dialog.registerCallback(DwtDialog.OK_BUTTON, this._handleDeviceWipe, this, [dialog, item, callback]); 192 dialog.popup(); 193 return; 194 } 195 } 196 197 item.doAction(action, callback); 198 }; 199 200 ZmMobileDevicesController.prototype._handleDeviceWipe = 201 function(dialog, item, callback) { 202 dialog.popdown(); 203 item.doAction(ZmOperation.MOBILE_WIPE, callback); 204 }; 205 206 ZmMobileDevicesController.prototype._handleAction = 207 function(item, id) { 208 if (id == ZmOperation.MOBILE_REMOVE) { 209 this._listView.removeItem(item, true); 210 this._devices.remove(item); 211 this._resetOperations(this._toolbar, 0); 212 return; 213 } 214 215 if (id == ZmOperation.MOBILE_WIPE) { 216 this._toolbar.getButton(ZmOperation.MOBILE_WIPE).setText(ZmMsg.mobileWipeCancel); 217 } 218 219 this._listView.redrawItem(item); 220 this._listView.setSelection(item, true); 221 this._resetOperations(this._toolbar, 1); 222 }; 223 224 /** 225 * Resets the toolbar button states, depending on which device is selected. 226 * 227 * @param parent [ZmButtonToolBar] the toolbar 228 * @param numSel [int] number of rules selected (0 or 1) 229 */ 230 ZmMobileDevicesController.prototype._resetOperations = 231 function(parent, numSel) { 232 if (numSel == 1) { 233 var item = this._listView.getSelection()[0]; 234 var status = item.getStatus(); 235 if (item.id == "AppleBADBAD") { 236 status = ZmMobileDevice.STATUS_REMOTE_WIPE_REQUESTED; 237 } 238 239 parent.enableAll(true); 240 parent.enable(ZmOperation.MOBILE_RESUME_SYNC, false); 241 242 if (status == ZmMobileDevice.STATUS_SUSPENDED) { 243 parent.enable(ZmOperation.MOBILE_SUSPEND_SYNC, false); 244 parent.enable(ZmOperation.MOBILE_RESUME_SYNC, true); 245 } 246 else { 247 var button = parent.getButton(ZmOperation.MOBILE_WIPE); 248 if (button) { 249 if (status == ZmMobileDevice.STATUS_REMOTE_WIPE_REQUESTED) { 250 button.setText(ZmMsg.mobileWipeCancel); 251 button.setImage("MobileWipeCancel"); 252 } else { 253 button.setText(ZmMsg.mobileWipe); 254 button.setImage("MobileWipe"); 255 } 256 } 257 if (status === ZmMobileDevice.STATUS_REMOTE_WIPE_COMPLETE) { 258 parent.enable(ZmOperation.MOBILE_WIPE, false); 259 } 260 261 } 262 263 if (!item.provisionable) { 264 parent.enable(ZmOperation.MOBILE_WIPE, false); 265 } 266 } 267 else { 268 parent.enableAll(false); 269 } 270 }; 271 272 ZmMobileDevicesController.handleRemoveOauthConsumerApp = function(removeLinkEle, oAuthAccessToken, oAuthAppName, oAuthDevice) { 273 var dialog = appCtxt.getOkCancelMsgDialog(); 274 var dialogContent = AjxMessageFormat.format(ZmMsg.oAuthAppAuthorizationRemoveConfirm, [oAuthAppName, oAuthDevice]); 275 dialog.setMessage(dialogContent, DwtMessageDialog.CRITICAL_STYLE, ZmMsg.removeOAuthAppAuthorization); 276 dialog.registerCallback(DwtDialog.OK_BUTTON, ZmMobileDevicesController.removeOauthConsumerApp.bind(null, removeLinkEle, dialog, oAuthAccessToken, oAuthAppName, oAuthDevice)); 277 dialog.popup(); 278 }; 279 280 ZmMobileDevicesController.removeOauthConsumerApp = function(removeLinkEle, dialog, oAuthAccessToken, oAuthAppName, oAuthDevice) { 281 var jsonObj = { RevokeOAuthConsumerRequest : { _jsns:"urn:zimbraAccount", accessToken:{ _content : oAuthAccessToken}}}; 282 var callback = ZmMobileDevicesController.removeOauthConsumerAppCallback.bind(null, removeLinkEle, dialog); 283 appCtxt.getRequestMgr().sendRequest({jsonObj:jsonObj, asyncMode:true, callback:callback}); 284 }; 285 286 ZmMobileDevicesController.removeOauthConsumerAppCallback = function(removeLinkEle, dialog) { 287 dialog.popdown(); 288 Dwt.setVisible(removeLinkEle, false); 289 };