1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/jsat/content-script.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,168 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +let Ci = Components.interfaces; 1.9 +let Cu = Components.utils; 1.10 + 1.11 +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); 1.12 +XPCOMUtils.defineLazyModuleGetter(this, 'Logger', 1.13 + 'resource://gre/modules/accessibility/Utils.jsm'); 1.14 +XPCOMUtils.defineLazyModuleGetter(this, 'Presentation', 1.15 + 'resource://gre/modules/accessibility/Presentation.jsm'); 1.16 +XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules', 1.17 + 'resource://gre/modules/accessibility/TraversalRules.jsm'); 1.18 +XPCOMUtils.defineLazyModuleGetter(this, 'Utils', 1.19 + 'resource://gre/modules/accessibility/Utils.jsm'); 1.20 +XPCOMUtils.defineLazyModuleGetter(this, 'EventManager', 1.21 + 'resource://gre/modules/accessibility/EventManager.jsm'); 1.22 +XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl', 1.23 + 'resource://gre/modules/accessibility/ContentControl.jsm'); 1.24 +XPCOMUtils.defineLazyModuleGetter(this, 'Roles', 1.25 + 'resource://gre/modules/accessibility/Constants.jsm'); 1.26 + 1.27 +Logger.debug('content-script.js'); 1.28 + 1.29 +let eventManager = null; 1.30 +let contentControl = null; 1.31 + 1.32 +function forwardToParent(aMessage) { 1.33 + // XXX: This is a silly way to make a deep copy 1.34 + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); 1.35 + newJSON.origin = 'child'; 1.36 + sendAsyncMessage(aMessage.name, newJSON); 1.37 +} 1.38 + 1.39 +function forwardToChild(aMessage, aListener, aVCPosition) { 1.40 + let acc = aVCPosition || Utils.getVirtualCursor(content.document).position; 1.41 + 1.42 + if (!Utils.isAliveAndVisible(acc) || acc.role != Roles.INTERNAL_FRAME) { 1.43 + return false; 1.44 + } 1.45 + 1.46 + Logger.debug(() => { 1.47 + return ['forwardToChild', Logger.accessibleToString(acc), 1.48 + aMessage.name, JSON.stringify(aMessage.json, null, ' ')]; 1.49 + }); 1.50 + 1.51 + let mm = Utils.getMessageManager(acc.DOMNode); 1.52 + 1.53 + if (aListener) { 1.54 + mm.addMessageListener(aMessage.name, aListener); 1.55 + } 1.56 + 1.57 + // XXX: This is a silly way to make a deep copy 1.58 + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); 1.59 + newJSON.origin = 'parent'; 1.60 + if (Utils.isContentProcess) { 1.61 + // XXX: OOP content's screen offset is 0, 1.62 + // so we remove the real screen offset here. 1.63 + newJSON.x -= content.mozInnerScreenX; 1.64 + newJSON.y -= content.mozInnerScreenY; 1.65 + } 1.66 + mm.sendAsyncMessage(aMessage.name, newJSON); 1.67 + return true; 1.68 +} 1.69 + 1.70 +function activateContextMenu(aMessage) { 1.71 + function sendContextMenuCoordinates(aAccessible) { 1.72 + let bounds = Utils.getBounds(aAccessible); 1.73 + sendAsyncMessage('AccessFu:ActivateContextMenu', {bounds: bounds}); 1.74 + } 1.75 + 1.76 + let position = Utils.getVirtualCursor(content.document).position; 1.77 + if (!forwardToChild(aMessage, activateContextMenu, position)) { 1.78 + sendContextMenuCoordinates(position); 1.79 + } 1.80 +} 1.81 + 1.82 +function presentCaretChange(aText, aOldOffset, aNewOffset) { 1.83 + if (aOldOffset !== aNewOffset) { 1.84 + let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset, 1.85 + aOldOffset, aOldOffset, true); 1.86 + sendAsyncMessage('AccessFu:Present', msg); 1.87 + } 1.88 +} 1.89 + 1.90 +function scroll(aMessage) { 1.91 + function sendScrollCoordinates(aAccessible) { 1.92 + let bounds = Utils.getBounds(aAccessible); 1.93 + sendAsyncMessage('AccessFu:DoScroll', 1.94 + { bounds: bounds, 1.95 + page: aMessage.json.page, 1.96 + horizontal: aMessage.json.horizontal }); 1.97 + } 1.98 + 1.99 + let position = Utils.getVirtualCursor(content.document).position; 1.100 + if (!forwardToChild(aMessage, scroll, position)) { 1.101 + sendScrollCoordinates(position); 1.102 + } 1.103 +} 1.104 + 1.105 +function adjustRange(aMessage) { 1.106 + function sendUpDownKey(aAccessible) { 1.107 + let acc = Utils.getEmbeddedControl(aAccessible) || aAccessible; 1.108 + let elem = acc.DOMNode; 1.109 + if (elem) { 1.110 + if (elem.tagName === 'INPUT' && elem.type === 'range') { 1.111 + elem[aMessage.json.direction === 'forward' ? 'stepDown' : 'stepUp'](); 1.112 + let changeEvent = content.document.createEvent('UIEvent'); 1.113 + changeEvent.initEvent('change', true, true); 1.114 + elem.dispatchEvent(changeEvent); 1.115 + } else { 1.116 + let evt = content.document.createEvent('KeyboardEvent'); 1.117 + let keycode = aMessage.json.direction == 'forward' ? 1.118 + content.KeyEvent.DOM_VK_DOWN : content.KeyEvent.DOM_VK_UP; 1.119 + evt.initKeyEvent( 1.120 + "keypress", false, true, null, false, false, false, false, keycode, 0); 1.121 + elem.dispatchEvent(evt); 1.122 + } 1.123 + } 1.124 + } 1.125 + 1.126 + let position = Utils.getVirtualCursor(content.document).position; 1.127 + if (!forwardToChild(aMessage, adjustRange, position)) { 1.128 + sendUpDownKey(position); 1.129 + } 1.130 +} 1.131 +addMessageListener( 1.132 + 'AccessFu:Start', 1.133 + function(m) { 1.134 + if (m.json.logLevel) { 1.135 + Logger.logLevel = Logger[m.json.logLevel]; 1.136 + } 1.137 + 1.138 + Logger.debug('AccessFu:Start'); 1.139 + if (m.json.buildApp) 1.140 + Utils.MozBuildApp = m.json.buildApp; 1.141 + 1.142 + addMessageListener('AccessFu:ContextMenu', activateContextMenu); 1.143 + addMessageListener('AccessFu:Scroll', scroll); 1.144 + addMessageListener('AccessFu:AdjustRange', adjustRange); 1.145 + 1.146 + if (!eventManager) { 1.147 + eventManager = new EventManager(this); 1.148 + } 1.149 + eventManager.start(); 1.150 + 1.151 + if (!contentControl) { 1.152 + contentControl = new ContentControl(this); 1.153 + } 1.154 + contentControl.start(); 1.155 + 1.156 + sendAsyncMessage('AccessFu:ContentStarted'); 1.157 + }); 1.158 + 1.159 +addMessageListener( 1.160 + 'AccessFu:Stop', 1.161 + function(m) { 1.162 + Logger.debug('AccessFu:Stop'); 1.163 + 1.164 + removeMessageListener('AccessFu:ContextMenu', activateContextMenu); 1.165 + removeMessageListener('AccessFu:Scroll', scroll); 1.166 + 1.167 + eventManager.stop(); 1.168 + contentControl.stop(); 1.169 + }); 1.170 + 1.171 +sendAsyncMessage('AccessFu:Ready');