content-script.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  3. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. var Ci = Components.interfaces;
  5. var Cu = Components.utils;
  6. Cu.import('resource://gre/modules/XPCOMUtils.jsm');
  7. XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
  8. 'resource://gre/modules/accessibility/Utils.jsm');
  9. XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
  10. 'resource://gre/modules/accessibility/Presentation.jsm');
  11. XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
  12. 'resource://gre/modules/accessibility/Utils.jsm');
  13. XPCOMUtils.defineLazyModuleGetter(this, 'EventManager',
  14. 'resource://gre/modules/accessibility/EventManager.jsm');
  15. XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl',
  16. 'resource://gre/modules/accessibility/ContentControl.jsm');
  17. XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
  18. 'resource://gre/modules/accessibility/Constants.jsm');
  19. XPCOMUtils.defineLazyModuleGetter(this, 'States',
  20. 'resource://gre/modules/accessibility/Constants.jsm');
  21. Logger.info('content-script.js', content.document.location);
  22. var eventManager = null;
  23. var contentControl = null;
  24. function forwardToParent(aMessage) {
  25. // XXX: This is a silly way to make a deep copy
  26. let newJSON = JSON.parse(JSON.stringify(aMessage.json));
  27. newJSON.origin = 'child';
  28. sendAsyncMessage(aMessage.name, newJSON);
  29. }
  30. function forwardToChild(aMessage, aListener, aVCPosition) {
  31. let acc = aVCPosition || Utils.getVirtualCursor(content.document).position;
  32. if (!Utils.isAliveAndVisible(acc) || acc.role != Roles.INTERNAL_FRAME) {
  33. return false;
  34. }
  35. Logger.debug(() => {
  36. return ['forwardToChild', Logger.accessibleToString(acc),
  37. aMessage.name, JSON.stringify(aMessage.json, null, ' ')];
  38. });
  39. let mm = Utils.getMessageManager(acc.DOMNode);
  40. if (aListener) {
  41. mm.addMessageListener(aMessage.name, aListener);
  42. }
  43. // XXX: This is a silly way to make a deep copy
  44. let newJSON = JSON.parse(JSON.stringify(aMessage.json));
  45. newJSON.origin = 'parent';
  46. if (Utils.isContentProcess) {
  47. // XXX: OOP content's screen offset is 0,
  48. // so we remove the real screen offset here.
  49. newJSON.x -= content.mozInnerScreenX;
  50. newJSON.y -= content.mozInnerScreenY;
  51. }
  52. mm.sendAsyncMessage(aMessage.name, newJSON);
  53. return true;
  54. }
  55. function activateContextMenu(aMessage) {
  56. let position = Utils.getVirtualCursor(content.document).position;
  57. if (!forwardToChild(aMessage, activateContextMenu, position)) {
  58. let center = Utils.getBounds(position, true).center();
  59. let evt = content.document.createEvent('HTMLEvents');
  60. evt.initEvent('contextmenu', true, true);
  61. evt.clientX = center.x;
  62. evt.clientY = center.y;
  63. position.DOMNode.dispatchEvent(evt);
  64. }
  65. }
  66. function presentCaretChange(aText, aOldOffset, aNewOffset) {
  67. if (aOldOffset !== aNewOffset) {
  68. let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
  69. aOldOffset, aOldOffset, true);
  70. sendAsyncMessage('AccessFu:Present', msg);
  71. }
  72. }
  73. function scroll(aMessage) {
  74. let position = Utils.getVirtualCursor(content.document).position;
  75. if (!forwardToChild(aMessage, scroll, position)) {
  76. sendAsyncMessage('AccessFu:DoScroll',
  77. { bounds: Utils.getBounds(position, true),
  78. page: aMessage.json.page,
  79. horizontal: aMessage.json.horizontal });
  80. }
  81. }
  82. addMessageListener(
  83. 'AccessFu:Start',
  84. function(m) {
  85. if (m.json.logLevel) {
  86. Logger.logLevel = Logger[m.json.logLevel];
  87. }
  88. Logger.debug('AccessFu:Start');
  89. if (m.json.buildApp)
  90. Utils.MozBuildApp = m.json.buildApp;
  91. addMessageListener('AccessFu:ContextMenu', activateContextMenu);
  92. addMessageListener('AccessFu:Scroll', scroll);
  93. if (!contentControl) {
  94. contentControl = new ContentControl(this);
  95. }
  96. contentControl.start();
  97. if (!eventManager) {
  98. eventManager = new EventManager(this, contentControl);
  99. }
  100. eventManager.inTest = m.json.inTest;
  101. eventManager.start();
  102. function contentStarted() {
  103. let accDoc = Utils.AccService.getAccessibleFor(content.document);
  104. if (accDoc && !Utils.getState(accDoc).contains(States.BUSY)) {
  105. sendAsyncMessage('AccessFu:ContentStarted');
  106. } else {
  107. content.setTimeout(contentStarted, 0);
  108. }
  109. }
  110. if (m.json.inTest) {
  111. // During a test we want to wait for the document to finish loading for
  112. // consistency.
  113. contentStarted();
  114. }
  115. });
  116. addMessageListener(
  117. 'AccessFu:Stop',
  118. function(m) {
  119. Logger.debug('AccessFu:Stop');
  120. removeMessageListener('AccessFu:ContextMenu', activateContextMenu);
  121. removeMessageListener('AccessFu:Scroll', scroll);
  122. eventManager.stop();
  123. contentControl.stop();
  124. });
  125. sendAsyncMessage('AccessFu:Ready');