accessible/src/jsat/content-script.js

changeset 0
6474c204b198
     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');

mercurial