<html><head>
<title>Test for bug 891247</title>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>

<script class="testbody" type="application/javascript">
  function ImageTester() {
    var counter = 0;
    var images = [];
    var that = this;

    this.add = function(aFile) {
      images.push(aFile);
    };

    this.test = function() {
      for (var i = 0; i < images.length; i++) {
        testImageSize(images[i]);
      }
    };

    this.returned = function() {
      counter++;
      info("returned=" + counter + " images.length=" + images.length);
      if (counter == images.length) {
        info("test finish");
        SimpleTest.finish();
      }
    };

    function testImageSize(aFile) {
      var source = window.URL.createObjectURL(aFile);
      var image = new Image();
      image.src = source;
      var imageTester = that;
      image.onload = function() {
        is(this.width, 62, "Check generated image width");
        is(this.height, 71, "Check generated image height");

        // This fails on OSX only.
        if (!navigator.platform.includes("Mac")) {
          testImageCanvas(image);
        }

        imageTester.returned();
      }

      document.body.appendChild(image);
    };

    function testImageCanvas(aImage) {
      var canvas = drawToCanvas(aImage);

      var refImage = document.getElementById('image');
      var refCanvas = drawToCanvas(refImage);

      is(canvas.toDataURL(), refCanvas.toDataURL(), "Image should map pixel-by-pixel");
    }

    function drawToCanvas(aImage) {
      var canvas = document.createElement("CANVAS");
      document.body.appendChild(canvas);
      canvas.width = aImage.width;
      canvas.height = aImage.height;
      canvas.getContext('2d').drawImage(aImage, 0, 0);
      return canvas;
    }
  }

  function copyImage(aImageId) {
    // selection of the node
    var node = document.getElementById(aImageId);
    var docShell = SpecialPowers.wrap(window).docShell;

    // let's copy the node
    var documentViewer = docShell.contentViewer
                         .QueryInterface(SpecialPowers.Ci.nsIContentViewerEdit);
    documentViewer.setCommandNode(node);
    documentViewer.copyImage(documentViewer.COPY_IMAGE_ALL);
  }

  function doTest() {
    SimpleTest.waitForExplicitFinish();

    copyImage('image');

    //--------- now check the content of the clipboard
    var clipboard = SpecialPowers.Cc["@mozilla.org/widget/clipboard;1"]
                                 .getService(SpecialPowers.Ci.nsIClipboard);
    // does the clipboard contain text/plain data ?
    ok(clipboard.hasDataMatchingFlavors(["text/plain"], clipboard.kGlobalClipboard),
       "clipboard contains unicode text");
    // does the clipboard contain text/html data ?
    ok(clipboard.hasDataMatchingFlavors(["text/html"], clipboard.kGlobalClipboard),
       "clipboard contains html text");
    // does the clipboard contain image data ?
    ok(clipboard.hasDataMatchingFlavors(["image/png"], clipboard.kGlobalClipboard),
       "clipboard contains image");

    window.addEventListener("paste", onPaste);

    var textarea = SpecialPowers.wrap(document.getElementById('textarea'));
    textarea.focus();
    textarea.editor.paste(clipboard.kGlobalClipboard);
  }

  function onPaste(e) {
    var imageTester = new ImageTester;
    testFiles(e, imageTester);
    testItems(e, imageTester);
    imageTester.test();
  }

  function testItems(e, imageTester) {
    var items = e.clipboardData.items;
    is(items, e.clipboardData.items,
       "Getting @items twice should return the same object");
    var haveFiles = false;
    ok(items instanceof DataTransferItemList, "@items implements DataTransferItemList");
    ok(items.length, "@items is not empty");
    for (var i = 0; i < items.length; i++) {
      var item = items[i];
      ok(item instanceof DataTransferItem, "each element of @items must implement DataTransferItem");
      if (item.kind == "file") {
        var file = item.getAsFile();
        ok(file instanceof File, ".getAsFile() returns a File object");
        ok(file.size > 0, "Files shouldn't have size 0");
        imageTester.add(file);
      }
    }
  }

  function testFiles(e, imageTester) {
    var files = e.clipboardData.files;

    is(files, e.clipboardData.files,
       "Getting the files array twice should return the same array");
    is(files.length, 1, "There should be one file in the clipboard");
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      ok(file instanceof File, ".files should contain only File objects");
      ok(file.size > 0, "This file shouldn't have size 0");
      if (navigator.platform.includes("Win")) {
        // On Windows the pasted file is (sometimes?) produced from the Windows only
        // file promise added by AppendImagePromise.
        ok(file.name == "image.png" || (file.name.startsWith("Untitled") && file.name.endsWith(".png")),
           `Correct filename, got "${file.name}"`);
      } else {
        is(file.name, "image.png", "Correct filename");
      }
      is(file.type, "image/png", "This file should be a image/png");

      testSlice(file);
      imageTester.add(file);
      // Adding the same image again so we can test concurrency
      imageTester.add(file);
    }
  }

  function testSlice(aFile) {
    var blob = aFile.slice();
    ok(blob instanceof Blob, ".slice returns a blob");
    is(blob.size, aFile.size, "the blob has the same size");

    blob = aFile.slice(123123);
    is(blob.size, 0, ".slice overflow check");

    blob = aFile.slice(123, 123141);
    is(blob.size, aFile.size - 123, ".slice @size check");

    blob = aFile.slice(123, 12);
    is(blob.size, 0, ".slice @size check 2");

    blob = aFile.slice(124, 134, "image/png");
    is(blob.size, 10, ".slice @size check 3");
    is(blob.type, "image/png", ".slice @type check");
  }

</script>
<body onload="doTest();">
  <img id="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABHCA
  IAAADQjmMaAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3goUAwAgSAORBwAAABl0RVh0Q29
  tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAABPSURBVGje7c4BDQAACAOga//OmuMbJGAurTbq
  6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6s31B0IqAY2/t
  QVCAAAAAElFTkSuQmCC" />
  <form>
    <textarea id="textarea"></textarea>
  </form>
</body>
</html>
