diff options
Diffstat (limited to 'accessible/jsat/content-script.js')
-rw-r--r-- | accessible/jsat/content-script.js | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/accessible/jsat/content-script.js b/accessible/jsat/content-script.js new file mode 100644 index 000000000..6ef0dadc3 --- /dev/null +++ b/accessible/jsat/content-script.js @@ -0,0 +1,151 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var Ci = Components.interfaces; +var Cu = Components.utils; + +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Logger', + 'resource://gre/modules/accessibility/Utils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Presentation', + 'resource://gre/modules/accessibility/Presentation.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Utils', + 'resource://gre/modules/accessibility/Utils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'EventManager', + 'resource://gre/modules/accessibility/EventManager.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl', + 'resource://gre/modules/accessibility/ContentControl.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Roles', + 'resource://gre/modules/accessibility/Constants.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'States', + 'resource://gre/modules/accessibility/Constants.jsm'); + +Logger.info('content-script.js', content.document.location); + +var eventManager = null; +var contentControl = null; + +function forwardToParent(aMessage) { + // XXX: This is a silly way to make a deep copy + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); + newJSON.origin = 'child'; + sendAsyncMessage(aMessage.name, newJSON); +} + +function forwardToChild(aMessage, aListener, aVCPosition) { + let acc = aVCPosition || Utils.getVirtualCursor(content.document).position; + + if (!Utils.isAliveAndVisible(acc) || acc.role != Roles.INTERNAL_FRAME) { + return false; + } + + Logger.debug(() => { + return ['forwardToChild', Logger.accessibleToString(acc), + aMessage.name, JSON.stringify(aMessage.json, null, ' ')]; + }); + + let mm = Utils.getMessageManager(acc.DOMNode); + + if (aListener) { + mm.addMessageListener(aMessage.name, aListener); + } + + // XXX: This is a silly way to make a deep copy + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); + newJSON.origin = 'parent'; + if (Utils.isContentProcess) { + // XXX: OOP content's screen offset is 0, + // so we remove the real screen offset here. + newJSON.x -= content.mozInnerScreenX; + newJSON.y -= content.mozInnerScreenY; + } + mm.sendAsyncMessage(aMessage.name, newJSON); + return true; +} + +function activateContextMenu(aMessage) { + let position = Utils.getVirtualCursor(content.document).position; + if (!forwardToChild(aMessage, activateContextMenu, position)) { + let center = Utils.getBounds(position, true).center(); + + let evt = content.document.createEvent('HTMLEvents'); + evt.initEvent('contextmenu', true, true); + evt.clientX = center.x; + evt.clientY = center.y; + position.DOMNode.dispatchEvent(evt); + } +} + +function presentCaretChange(aText, aOldOffset, aNewOffset) { + if (aOldOffset !== aNewOffset) { + let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset, + aOldOffset, aOldOffset, true); + sendAsyncMessage('AccessFu:Present', msg); + } +} + +function scroll(aMessage) { + let position = Utils.getVirtualCursor(content.document).position; + if (!forwardToChild(aMessage, scroll, position)) { + sendAsyncMessage('AccessFu:DoScroll', + { bounds: Utils.getBounds(position, true), + page: aMessage.json.page, + horizontal: aMessage.json.horizontal }); + } +} + +addMessageListener( + 'AccessFu:Start', + function(m) { + if (m.json.logLevel) { + Logger.logLevel = Logger[m.json.logLevel]; + } + + Logger.debug('AccessFu:Start'); + if (m.json.buildApp) + Utils.MozBuildApp = m.json.buildApp; + + addMessageListener('AccessFu:ContextMenu', activateContextMenu); + addMessageListener('AccessFu:Scroll', scroll); + + if (!contentControl) { + contentControl = new ContentControl(this); + } + contentControl.start(); + + if (!eventManager) { + eventManager = new EventManager(this, contentControl); + } + eventManager.inTest = m.json.inTest; + eventManager.start(); + + function contentStarted() { + let accDoc = Utils.AccService.getAccessibleFor(content.document); + if (accDoc && !Utils.getState(accDoc).contains(States.BUSY)) { + sendAsyncMessage('AccessFu:ContentStarted'); + } else { + content.setTimeout(contentStarted, 0); + } + } + + if (m.json.inTest) { + // During a test we want to wait for the document to finish loading for + // consistency. + contentStarted(); + } + }); + +addMessageListener( + 'AccessFu:Stop', + function(m) { + Logger.debug('AccessFu:Stop'); + + removeMessageListener('AccessFu:ContextMenu', activateContextMenu); + removeMessageListener('AccessFu:Scroll', scroll); + + eventManager.stop(); + contentControl.stop(); + }); + +sendAsyncMessage('AccessFu:Ready'); |