summaryrefslogtreecommitdiffstats
path: root/accessible/jsat/content-script.js
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/jsat/content-script.js')
-rw-r--r--accessible/jsat/content-script.js151
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');