<?xml version="1.0"?>

<!-- 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/. -->

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet
  href="chrome://mochikit/content/tests/SimpleTest/test.css"
  type="text/css"?>

<window id="263683test"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        width="600"
        height="600"
        onload="SimpleTest.executeSoon(startTest);"
        title="263683 test">

  <script type="application/javascript"><![CDATA[
    const {interfaces: Ci, classes: Cc, results: Cr, utils: Cu} = Components;
    Cu.import("resource://gre/modules/AppConstants.jsm");
    Cu.import("resource://gre/modules/Task.jsm");
    Cu.import("resource://testing-common/BrowserTestUtils.jsm");
    Cu.import("resource://testing-common/ContentTask.jsm");
    ContentTask.setTestScope(window.opener.wrappedJSObject);

    var gPrefsvc = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
    var gFindBar = null;
    var gBrowser;

    var imports = ["SimpleTest", "ok", "info", "is"];
    for (var name of imports) {
      window[name] = window.opener.wrappedJSObject[name];
    }

    function startTest() {
      Task.spawn(function* () {
        gFindBar = document.getElementById("FindToolbar");
        for (let browserId of ["content", "content-remote"]) {
          yield startTestWithBrowser(browserId);
        }
      }).then(() => {
        window.close();
        SimpleTest.finish();
      });
    }

    function* startTestWithBrowser(browserId) {
      // We're bailing out when testing a remote browser on OSX 10.6, because it
      // fails permanently.
      if (browserId.endsWith("remote") && AppConstants.isPlatformAndVersionAtMost("macosx", 11)) {
        return;
      }

      info("Starting test with browser '" + browserId + "'");
      gBrowser = document.getElementById(browserId);
      gFindBar.browser = gBrowser;
      let promise = BrowserTestUtils.browserLoaded(gBrowser);
      gBrowser.loadURI('data:text/html,<h2>Text mozilla</h2><input id="inp" type="text" />');
      yield promise;
      yield onDocumentLoaded();
    }

    function toggleHighlightAndWait(highlight) {
      return new Promise(resolve => {
        let listener = {
          onHighlightFinished: function() {
            gFindBar.browser.finder.removeResultListener(listener);
            resolve();
          }
        };
        gFindBar.browser.finder.addResultListener(listener);
        gFindBar.toggleHighlight(highlight);
      });
    }

    function* onDocumentLoaded() {
      gFindBar.open();
      var search = "mozilla";
      gFindBar._findField.focus();
      gFindBar._findField.value = search;
      var matchCase = gFindBar.getElement("find-case-sensitive");
      if (matchCase.checked) {
        matchCase.doCommand();
      }

      yield toggleHighlightAndWait(true);
      gFindBar._find();

      yield ContentTask.spawn(gBrowser, { search }, function* (args) {
        let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsISelectionDisplay)
                                 .QueryInterface(Ci.nsISelectionController);
        Assert.ok("SELECTION_FIND" in controller, "Correctly detects new selection type");
        let selection = controller.getSelection(controller.SELECTION_FIND);

        Assert.equal(selection.rangeCount, 1,
          "Correctly added a match to the selection type");
        Assert.equal(selection.getRangeAt(0).toString().toLowerCase(),
          args.search, "Added the correct match");
      });

      yield toggleHighlightAndWait(false);

      yield ContentTask.spawn(gBrowser, { search }, function* (args) {
        let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsISelectionDisplay)
                                 .QueryInterface(Ci.nsISelectionController);
        let selection = controller.getSelection(controller.SELECTION_FIND);
        Assert.equal(selection.rangeCount, 0, "Correctly removed the range");

        let input = content.document.getElementById("inp");
        input.value = args.search;
      });
 
      yield toggleHighlightAndWait(true);

      yield ContentTask.spawn(gBrowser, { search }, function* (args) {
        let input = content.document.getElementById("inp");
        let inputController = input.editor.selectionController;
        let inputSelection = inputController.getSelection(inputController.SELECTION_FIND);

        Assert.equal(inputSelection.rangeCount, 1,
          "Correctly added a match from input to the selection type");
        Assert.equal(inputSelection.getRangeAt(0).toString().toLowerCase(),
          args.search, "Added the correct match");
      });

      yield toggleHighlightAndWait(false);

      yield ContentTask.spawn(gBrowser, null, function* () {
        let input = content.document.getElementById("inp");
        let inputController = input.editor.selectionController;
        let inputSelection = inputController.getSelection(inputController.SELECTION_FIND);

        Assert.equal(inputSelection.rangeCount, 0, "Correctly removed the range");
      });

      // For posterity, test iframes too.

      let promise = BrowserTestUtils.browserLoaded(gBrowser);
      gBrowser.loadURI('data:text/html,<h2>Text mozilla</h2><iframe id="leframe" ' +
        'src="data:text/html,Text mozilla"></iframe>');
      yield promise;

      yield toggleHighlightAndWait(true);

      yield ContentTask.spawn(gBrowser, { search }, function* (args) {
        function getSelection(docShell) {
          let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                   .getInterface(Ci.nsISelectionDisplay)
                                   .QueryInterface(Ci.nsISelectionController);
          return controller.getSelection(controller.SELECTION_FIND);
        }

        let selection = getSelection(docShell);
        Assert.equal(selection.rangeCount, 1,
          "Correctly added a match to the selection type");
        Assert.equal(selection.getRangeAt(0).toString().toLowerCase(),
          args.search, "Added the correct match");

        // Check the iframe too:
        let frame = content.document.getElementById("leframe");
        // Hoops! Get the docShell first, then the selection.
        selection = getSelection(frame.contentWindow
          .QueryInterface(Ci.nsIInterfaceRequestor)
          .getInterface(Ci.nsIWebNavigation)
          .QueryInterface(Ci.nsIDocShell));
        Assert.equal(selection.rangeCount, 1,
          "Correctly added a match to the selection type");
        Assert.equal(selection.getRangeAt(0).toString().toLowerCase(),
          args.search, "Added the correct match");
      });

      yield toggleHighlightAndWait(false);

      let matches = gFindBar._foundMatches.value.match(/([\d]*)\sof\s([\d]*)/);
      is(matches[1], "2", "Found correct amount of matches")

      yield ContentTask.spawn(gBrowser, null, function* (args) {
        function getSelection(docShell) {
          let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                   .getInterface(Ci.nsISelectionDisplay)
                                   .QueryInterface(Ci.nsISelectionController);
          return controller.getSelection(controller.SELECTION_FIND);
        }

        let selection = getSelection(docShell);
        Assert.equal(selection.rangeCount, 0, "Correctly removed the range");

        // Check the iframe too:
        let frame = content.document.getElementById("leframe");
        // Hoops! Get the docShell first, then the selection.
        selection = getSelection(frame.contentWindow
          .QueryInterface(Ci.nsIInterfaceRequestor)
          .getInterface(Ci.nsIWebNavigation)
          .QueryInterface(Ci.nsIDocShell));
        Assert.equal(selection.rangeCount, 0, "Correctly removed the range");

        content.document.documentElement.focus();
      });

      gFindBar.close(true);
    }
  ]]></script>

  <browser type="content-primary" flex="1" id="content" src="about:blank"/>
  <browser type="content-primary" flex="1" id="content-remote" remote="true" src="about:blank"/>
  <findbar id="FindToolbar" browserid="content"/>
</window>