testing/marionette/ChromeUtils.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /**
     6  * ChromeUtils.js is a set of mochitest utilities that are used to 
     7  * synthesize events in the browser.  These are only used by 
     8  * mochitest-chrome and browser-chrome tests.  Originally these functions were in 
     9  * EventUtils.js, but when porting to specialPowers, we didn't want
    10  * to move unnecessary functions.
    11  *
    12  * ChromeUtils.js depends on EventUtils.js being loaded.
    13  *
    14  */
    16 /**
    17  * Synthesize a query text content event.
    18  *
    19  * @param aOffset  The character offset.  0 means the first character in the
    20  *                 selection root.
    21  * @param aLength  The length of getting text.  If the length is too long,
    22  *                 the extra length is ignored.
    23  * @param aWindow  Optional (If null, current |window| will be used)
    24  * @return         An nsIQueryContentEventResult object.  If this failed,
    25  *                 the result might be null.
    26  */
    27 function synthesizeQueryTextContent(aOffset, aLength, aWindow)
    28 {
    29   var utils = _getDOMWindowUtils(aWindow);
    30   if (!utils) {
    31     return nullptr;
    32   }
    33   return utils.sendQueryContentEvent(utils.QUERY_TEXT_CONTENT,
    34                                      aOffset, aLength, 0, 0);
    35 }
    37 /**
    38  * Synthesize a query caret rect event.
    39  *
    40  * @param aOffset  The caret offset.  0 means left side of the first character
    41  *                 in the selection root.
    42  * @param aWindow  Optional (If null, current |window| will be used)
    43  * @return         An nsIQueryContentEventResult object.  If this failed,
    44  *                 the result might be null.
    45  */
    46 function synthesizeQueryCaretRect(aOffset, aWindow)
    47 {
    48   var utils = _getDOMWindowUtils(aWindow);
    49   if (!utils) {
    50     return nullptr;
    51   }
    52   return utils.sendQueryContentEvent(utils.QUERY_CARET_RECT,
    53                                      aOffset, 0, 0, 0);
    54 }
    56 /**
    57  * Synthesize a query text rect event.
    58  *
    59  * @param aOffset  The character offset.  0 means the first character in the
    60  *                 selection root.
    61  * @param aLength  The length of the text.  If the length is too long,
    62  *                 the extra length is ignored.
    63  * @param aWindow  Optional (If null, current |window| will be used)
    64  * @return         An nsIQueryContentEventResult object.  If this failed,
    65  *                 the result might be null.
    66  */
    67 function synthesizeQueryTextRect(aOffset, aLength, aWindow)
    68 {
    69   var utils = _getDOMWindowUtils(aWindow);
    70   if (!utils) {
    71     return nullptr;
    72   }
    73   return utils.sendQueryContentEvent(utils.QUERY_TEXT_RECT,
    74                                      aOffset, aLength, 0, 0);
    75 }
    77 /**
    78  * Synthesize a query editor rect event.
    79  *
    80  * @param aWindow  Optional (If null, current |window| will be used)
    81  * @return         An nsIQueryContentEventResult object.  If this failed,
    82  *                 the result might be null.
    83  */
    84 function synthesizeQueryEditorRect(aWindow)
    85 {
    86   var utils = _getDOMWindowUtils(aWindow);
    87   if (!utils) {
    88     return nullptr;
    89   }
    90   return utils.sendQueryContentEvent(utils.QUERY_EDITOR_RECT, 0, 0, 0, 0);
    91 }
    93 /**
    94  * Synthesize a character at point event.
    95  *
    96  * @param aX, aY   The offset in the client area of the DOM window.
    97  * @param aWindow  Optional (If null, current |window| will be used)
    98  * @return         An nsIQueryContentEventResult object.  If this failed,
    99  *                 the result might be null.
   100  */
   101 function synthesizeCharAtPoint(aX, aY, aWindow)
   102 {
   103   var utils = _getDOMWindowUtils(aWindow);
   104   if (!utils) {
   105     return nullptr;
   106   }
   107   return utils.sendQueryContentEvent(utils.QUERY_CHARACTER_AT_POINT,
   108                                      0, 0, aX, aY);
   109 }
   111 /**
   112  * Emulate a dragstart event.
   113  *  element - element to fire the dragstart event on
   114  *  expectedDragData - the data you expect the data transfer to contain afterwards
   115  *                      This data is in the format:
   116  *                         [ [ {type: value, data: value, test: function}, ... ], ... ]
   117  *                     can be null
   118  *  aWindow - optional; defaults to the current window object.
   119  *  x - optional; initial x coordinate
   120  *  y - optional; initial y coordinate
   121  * Returns null if data matches.
   122  * Returns the event.dataTransfer if data does not match
   123  *
   124  * eqTest is an optional function if comparison can't be done with x == y;
   125  *   function (actualData, expectedData) {return boolean}
   126  *   @param actualData from dataTransfer
   127  *   @param expectedData from expectedDragData
   128  * see bug 462172 for example of use
   129  *
   130  */
   131 function synthesizeDragStart(element, expectedDragData, aWindow, x, y)
   132 {
   133   if (!aWindow)
   134     aWindow = window;
   135   x = x || 2;
   136   y = y || 2;
   137   const step = 9;
   139   var result = "trapDrag was not called";
   140   var trapDrag = function(event) {
   141     try {
   142       var dataTransfer = event.dataTransfer;
   143       result = null;
   144       if (!dataTransfer)
   145         throw "no dataTransfer";
   146       if (expectedDragData == null ||
   147           dataTransfer.mozItemCount != expectedDragData.length)
   148         throw dataTransfer;
   149       for (var i = 0; i < dataTransfer.mozItemCount; i++) {
   150         var dtTypes = dataTransfer.mozTypesAt(i);
   151         if (dtTypes.length != expectedDragData[i].length)
   152           throw dataTransfer;
   153         for (var j = 0; j < dtTypes.length; j++) {
   154           if (dtTypes[j] != expectedDragData[i][j].type)
   155             throw dataTransfer;
   156           var dtData = dataTransfer.mozGetDataAt(dtTypes[j],i);
   157           if (expectedDragData[i][j].eqTest) {
   158             if (!expectedDragData[i][j].eqTest(dtData, expectedDragData[i][j].data))
   159               throw dataTransfer;
   160           }
   161           else if (expectedDragData[i][j].data != dtData)
   162             throw dataTransfer;
   163         }
   164       }
   165     } catch(ex) {
   166       result = ex;
   167     }
   168     event.preventDefault();
   169     event.stopPropagation();
   170   }
   171   aWindow.addEventListener("dragstart", trapDrag, false);
   172   synthesizeMouse(element, x, y, { type: "mousedown" }, aWindow);
   173   x += step; y += step;
   174   synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
   175   x += step; y += step;
   176   synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
   177   aWindow.removeEventListener("dragstart", trapDrag, false);
   178   synthesizeMouse(element, x, y, { type: "mouseup" }, aWindow);
   179   return result;
   180 }
   182 /**
   183  * Emulate a drop by emulating a dragstart and firing events dragenter, dragover, and drop.
   184  *  srcElement - the element to use to start the drag, usually the same as destElement
   185  *               but if destElement isn't suitable to start a drag on pass a suitable
   186  *               element for srcElement
   187  *  destElement - the element to fire the dragover, dragleave and drop events
   188  *  dragData - the data to supply for the data transfer
   189  *                     This data is in the format:
   190  *                       [ [ {type: value, data: value}, ...], ... ]
   191  *  dropEffect - the drop effect to set during the dragstart event, or 'move' if null
   192  *  aWindow - optional; defaults to the current window object.
   193  *  eventUtils - optional; allows you to pass in a reference to EventUtils.js. 
   194  *               If the eventUtils parameter is not passed in, we assume EventUtils.js is 
   195  *               in the scope. Used by browser-chrome tests.
   196  *
   197  * Returns the drop effect that was desired.
   198  */
   199 function synthesizeDrop(srcElement, destElement, dragData, dropEffect, aWindow, eventUtils)
   200 {
   201   if (!aWindow)
   202     aWindow = window;
   204   var synthesizeMouseAtCenter = (eventUtils || window).synthesizeMouseAtCenter;
   205   var synthesizeMouse = (eventUtils || window).synthesizeMouse;
   207   var gWindowUtils  = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   208                              getInterface(Components.interfaces.nsIDOMWindowUtils);
   209   var ds = Components.classes["@mozilla.org/widget/dragservice;1"].
   210            getService(Components.interfaces.nsIDragService);
   212   var dataTransfer;
   213   var trapDrag = function(event) {
   214     dataTransfer = event.dataTransfer;
   215     for (var i = 0; i < dragData.length; i++) {
   216       var item = dragData[i];
   217       for (var j = 0; j < item.length; j++) {
   218         dataTransfer.mozSetDataAt(item[j].type, item[j].data, i);
   219       }
   220     }
   221     dataTransfer.dropEffect = dropEffect || "move";
   222     event.preventDefault();
   223     event.stopPropagation();
   224   }
   226   ds.startDragSession();
   228   try {
   229     // need to use real mouse action
   230     aWindow.addEventListener("dragstart", trapDrag, true);
   231     synthesizeMouseAtCenter(srcElement, { type: "mousedown" }, aWindow);
   233     var rect = srcElement.getBoundingClientRect();
   234     var x = rect.width / 2;
   235     var y = rect.height / 2;
   236     synthesizeMouse(srcElement, x, y, { type: "mousemove" }, aWindow);
   237     synthesizeMouse(srcElement, x+10, y+10, { type: "mousemove" }, aWindow);
   238     aWindow.removeEventListener("dragstart", trapDrag, true);
   240     event = aWindow.document.createEvent("DragEvents");
   241     event.initDragEvent("dragenter", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
   242     gWindowUtils.dispatchDOMEventViaPresShell(destElement, event, true);
   244     var event = aWindow.document.createEvent("DragEvents");
   245     event.initDragEvent("dragover", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
   246     if (gWindowUtils.dispatchDOMEventViaPresShell(destElement, event, true)) {
   247       synthesizeMouseAtCenter(destElement, { type: "mouseup" }, aWindow);
   248       return "none";
   249     }
   251     if (dataTransfer.dropEffect != "none") {
   252       event = aWindow.document.createEvent("DragEvents");
   253       event.initDragEvent("drop", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
   254       gWindowUtils.dispatchDOMEventViaPresShell(destElement, event, true);
   255     }
   257     synthesizeMouseAtCenter(destElement, { type: "mouseup" }, aWindow);
   259     return dataTransfer.dropEffect;
   260   } finally {
   261     ds.endDragSession(true);
   262   }
   263 };
   265 var PluginUtils =
   266 {
   267   withTestPlugin : function(callback)
   268   {
   269     if (typeof Components == "undefined")
   270     {
   271       todo(false, "Not a Mozilla-based browser");
   272       return false;
   273     }
   275     var ph = Components.classes["@mozilla.org/plugin/host;1"]
   276                        .getService(Components.interfaces.nsIPluginHost);
   277     var tags = ph.getPluginTags();
   279     // Find the test plugin
   280     for (var i = 0; i < tags.length; i++)
   281     {
   282       if (tags[i].name == "Test Plug-in")
   283       {
   284         callback(tags[i]);
   285         return true;
   286       }
   287     }
   288     todo(false, "Need a test plugin on this platform");
   289     return false;
   290   }
   291 };

mercurial