chromium/third_party/blink/web_tests/editing/pasteboard/copy-crash.html

<html>
  <head>
    <script src="../editing.js" language="JavaScript" type="text/JavaScript" ></script>
    <style type="text/css">
      div.popup {
        color: black !important;
        background: yellow !important;
        padding: 0.5em !important;
        position: absolute !important;
        z-index: 20000 !important;
        display: none;
      }
    </style>
    <script type="text/javascript">
      function getAbsolutePosition(element) {
        var r = { x: element.offsetLeft, y: element.offsetTop };
        if (element.offsetParent) {
          var tmp = getAbsolutePosition(element.offsetParent);
          r.x += tmp.x;
          r.y += tmp.y;
        }
        return r;
      }

      function runTest1() {
        if (!window.testRunner)
          return;
        testRunner.waitUntilDone();
        testRunner.dumpAsText();

        e = document.getElementById("mouse_target");
        r = getAbsolutePosition(e);
        x = r.x + e.offsetLeft + e.offsetWidth / 2;
        y = r.y + e.offsetTop + e.offsetHeight / 2;
        eventSender.mouseMoveTo(x, y);
        window.setTimeout("runTest2()", 400);
      }

      function runTest2() {
        e = document.getElementById("select_target");
        r = getAbsolutePosition(e);

        setSelectionCommand(e, 0, e, 1);
        eventSender.mouseMoveTo(0, 0);
        window.setTimeout("runTest3()", 200);
      }

      function runTest3() {
        copyCommand();
        testRunner.notifyDone();
      }

      function MPP_bind(fn, self, var_args) {
        var boundargs = fn.boundArgs_ || [];
        boundargs = boundargs.concat(Array.prototype.slice.call(arguments, 2));

        if (typeof fn.boundSelf_ != 'undefined') {
          self = fn.boundSelf_;
        }

        if (typeof fn.foundFn_ != 'undefined') {
          fn = fn.boundFn_;
        }

        var newfn = function() {
          var args = boundargs.concat(Array.prototype.slice.call(arguments));
          return fn.apply(self, args);
        }

        newfn.boundArgs_ = boundargs;
        newfn.boundSelf_ = self;
        newfn.boundFn_ = fn;

        return newfn;
      };

      function PersonPopup() {
        this.pointerPosX = 0;
        this.pointerPosY = 0;

        this.pointerOnTargetElement = false;

        this.targetPosX = 0;
        this.targetPosY = 0;
        this.targetWidth = 0;
        this.targetHeight = 0;
        this.targetElement = 0;

        this.delayed = false;
        this.visible = false;
        this.pointerOutsidePopup = false;

        this.showTimerID = -1;
        this.hideTimerID = -1;

        window.addEventListener('load',
                                MPP_bind(this.handleOnLoad_, this), null);

      };

      PersonPopup.prototype.getPointerX_ = function(e) {
        var x, scrollLeft;

        if (e.pageX) {
          x = e.pageX;
        } else if (e.clientX) {
          x = e.clientX + document.scrollingElement.scrollLeft;
        } else {
          x = 0;
        }
        return x;
      };

      PersonPopup.prototype.getPointerY_ = function(e) {
        var y, scrollTop;

        if (e.pageY) {
          y = e.pageY;
        } else if (e.clientY) {
          y = e.clientY + document.scrollingElement.scrollTop;
        } else {
          y = 0;
        }
        return y;
      };

      PersonPopup.prototype.pointerCloseEnough_ = function(x, y) {
        var POINTER_TOLERANCE = 5;
        if (this.pointerOutsidePopup) {
          if ((x >= this.targetPosX) &&
              (x <= this.targetPosX + this.targetWidth) &&
              (y >= this.targetPosY) &&
              (y <= this.targetPosY + this.targetHeight)) {
            this.pointerOutsidePopup = false;
            return true;
          }
        } else {
          if ((x >= this.targetPosX - POINTER_TOLERANCE) &&
              (x <= this.targetPosX + this.targetWidth +
                    POINTER_TOLERANCE) &&
              (y >= this.targetPosY - POINTER_TOLERANCE) &&
              (y <= this.targetPosY + this.targetHeight +
                    POINTER_TOLERANCE)) {
            this.pointerOutsidePopup = false;
            return true;
          }
        }

        return false;
      };

      PersonPopup.prototype.handleMouseMove_ = function(e) {
        if ((this.delayed) || (this.visible)) {
          e = e || window.event;

          var x = this.getPointerX_(e);
          var y = this.getPointerY_(e);

          if (this.pointerCloseEnough_(x, y)) {
            if (this.hideTimerID) {
              window.clearTimeout(this.hideTimerID);
              this.hideTimerID = -1;
            }
          } else {
            if (this.hideTimerID == -1) {
              this.hideTimerID = window.setTimeout(MPP_bind(this.hide_, this),
                                                   200);
            }
          }
        }
      };

      PersonPopup.prototype.resizeElement_ = function(el, x, y, w, h) {
        if (x != false) {
          el.style.left = x + 'px';
        }
        if (y != false) {
          el.style.top = y + 'px';
        }
        if (w != false) {
          el.style.width = w + 'px';
        }
        if (h != false) {
          el.style.height = h + 'px';
        }
      };

      PersonPopup.prototype.show_ = function() {
        this.showTimerID = -1;

        if (this.hideTimerID != -1) {
          this.delayed = false;
          return;
        }
        if (!this.pointerOnTargetElement) {
          this.delayed = false;
          return;
        }
        this.resizeElement_(this.popupDetailedElement,
                            this.targetPosX, this.targetPosY,
                            this.targetWidth, false);
        this.popupDetailedElement.style.display = 'block';
        this.popupDetailedElement.innerHTML = "<a href='http://dnede.com' id='select_target'>Select</a>";
        this.popupDetailedElement.style.visibility = 'visible';
        this.visible = true;
        this.delayed = false;
      };

      PersonPopup.prototype.hide_ = function() {
        this.hideTimerID = -1;
        this.popupDetailedElement.style.display = 'none';
        this.visible = false;
        this.delayed = false;
      };

      PersonPopup.prototype.handleAnchorMouseMove_ = function(e) {
        e = e || window.event;

        var targetElement = (e.target) ? e.target : e.srcElement;

        this.pointerOnTargetElement = true;

        if (targetElement == this.targetElement) {
          this.x = this.getPointerX_(e);
          this.y = this.getPointerY_(e);

        } else {
          this.handleAnchorMouseOver_(e);
        }
      };

      PersonPopup.prototype.handleAnchorMouseOver_ = function(e) {
        e = e || window.event;
        var targetElement = (e.target) ? e.target : e.srcElement;

        if (this.visible &&
            (targetElement == this.targetElement) &&
            (this.hideTimerID == -1)) {
          return;
        }

        this.x = this.getPointerX_(e);
        this.y = this.getPointerY_(e);

        if (this.visible &&
            (targetElement != this.targetElement) &&
            (this.pointerCloseEnough_(this.x, this.y))) {
          return;
        }

        if (this.delayed && (this.targetElement == targetElement)) {
          return;
        }

        this.targetElement = targetElement;
        var screenWidth = self.innerWidth;
        var screenHeight = self.innerHeight;
        var scrollTop = document.documentElement.scrollTop;
        var scrollLeft = document.documentElement.scrollLeft;
        this.targetWidth = 12.7 * 26;
        this.targetHeight = 12.7 * 13;
        this.targetPosX = Math.floor(this.x + 15);
        this.targetPosY = Math.floor(this.y + 20);

        if (this.showTimerID != -1) {
          window.clearTimeout(this.showTimerID);
        }

        if (this.visible) {
          this.popupDetailedElement.style.display = 'none';
          this.showTimerID =
            window.setTimeout(MPP_bind(this.show_, this), 200);
        } else {
          this.showTimerID =
            window.setTimeout(MPP_bind(this.show_, this), 350);
        }

        this.delayed = true;
        this.pointerOutsidePopup = true;
      };

      PersonPopup.prototype.handleMouseOut_ = function(e) {
        if ((this.delayed) || (this.visible)) {

          this.pointerOnTargetElement = false;

          e = e || window.event;

          if (e) {
            var from = null;

            if (e.relatedTarget) {
              from = e.relatedTarget;
            } else if (e.toElement) {
              from = e.toElement;
            }

            var targetElement = (e.target) ? e.target : e.srcElement;

            try {
              if ((from == null) || (from.tagName == 'HTML') ||
                  (from.tagName.substring(0, 3) == 'xul')) {
                this.hideTimerID =
                  window.setTimeout(MPP_bind(this.hide_, this),
                                    200);
              }
            } catch(e) {

            }
          }
        }
      };

      PersonPopup.prototype.handleOnLoad_ = function(e) {
        e = e || window.event;
        this.popupDetailedElement = document.createElement('div');
        this.popupDetailedElement.
            setAttribute('id','popup_detailed');
        this.popupDetailedElement.className = 'popup';
        this.popupDetailedElement.style.display = 'none';
        this.popupDetailedElement.style.position = 'absolute';
        this.popupDetailedElement.innerHTML = '&nbsp;';
        document.body.appendChild(this.popupDetailedElement);

        document.body.onmousemove = MPP_bind(this.handleMouseMove_, this);
        document.body.onmouseout = MPP_bind(this.handleMouseOut_, this);
        this.enablePopupsForChildElements(document);
        
        runTest1();
      };

      PersonPopup.prototype.enablePopupsForChildElements = function(el) {
        var els = el.getElementsByTagName('*');

        for (var i = 0, item; item = els[i]; i++) {
          if (item.className.indexOf('showPersonPopup') != -1) {
            item.onmouseover = MPP_bind(this.handleAnchorMouseOver_, this);
            item.onmousemove = MPP_bind(this.handleAnchorMouseMove_, this);
          }
        }
      };
      
      var personPopup = new PersonPopup();
    </script>
  </head>
  <body>
    <p class="byline">
        <a class="showPersonPopup" id="mouse_target" href="dummy">Mouse Over</a>
    </p>
    <div id="log_div">
      This test checks the fix for https://bugs.webkit.org/show_bug.cgi?id=18506. To test it manually:
      <li/> Hover mouse over "Mouse Over" link
      <li/> Quickly jump to the yellow box that pops up and select "Select" link
      <li/> Move mouse away so that pop up disappears
      <li/> Press the "Copy" keyboard accelerator - this should not cause any crash
    </div>
  </body>
</html>