<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=61098
-->
<head>
  <title>Test for Bug 61098</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="application/javascript" src="/tests/SimpleTest/MockObjects.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="runtests();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=61098">Mozilla Bug 61098</a>
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="text/javascript">
/** Test for Bug 61098 **/

SimpleTest.waitForExplicitFinish();

var mockPromptServiceRegisterer, mockPromptFactoryRegisterer;

var promptState;

function registerMockPromptService()
{
  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
  var XPCOMUtils = SpecialPowers.Cu.import("resource://gre/modules/XPCOMUtils.jsm").XPCOMUtils;
  var Ci = SpecialPowers.Ci;

  function MockPrompt(aDOMWindow) {
    this.domWindow = aDOMWindow;
  }

  MockPrompt.prototype = {
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrompt]),

    domWindow : null,

    _toggleModalState: function()
    {
      // The real prompt service puts the window into a modal state
      // immediately before showing a modal prompt, and leaves the modal state
      // when the prompt is dismissed by the user. This mock prompt doesn't
      // show anything to the user, so we only need to enter and immediately
      // leave the modal state -- this is done to trigger the necessary
      // accounting for triggering the "stop showing more prompts" code for
      // abusive pages.
      var winUtils = SpecialPowers.getDOMWindowUtils(this.domWindow);
      winUtils.enterModalState();
      winUtils.leaveModalState();
    },

    alert: function(aDialogTitle, aText)
    {
      this._toggleModalState();
      promptState = {method: "alert",
                     parent: this.domWindow,
                     title: aDialogTitle,
                     msg: aText
      };
    },

    alertCheck: function(aDialogTitle, aText, aCheckMsg, aCheckState)
    {
      this._toggleModalState();
      promptState = {method: "alertCheck",
                     parent: this.domWindow,
                     title: aDialogTitle,
                     msg: aText,
                     checkMsg: aCheckMsg,
                     checkState: aCheckState
      };

      SpecialPowers.wrap(aCheckState).value = true;
    },

    confirm: function(aDialogTitle, aText)
    {
      this._toggleModalState();
      promptState = {method: "confirm",
                     parent: this.domWindow,
                     title: aDialogTitle,
                     msg: aText
      };

      return true;
    },

    confirmCheck: function(aDialogTitle, aText, aCheckMsg, aCheckState)
    {
      this._toggleModalState();
      promptState = {method: "confirmCheck",
                     parent: this.domWindow,
                     title: aDialogTitle,
                     msg: aText,
                     checkMsg: aCheckMsg,
                     checkState: aCheckState
      };

      SpecialPowers.wrap(aCheckState).value = true;

      return true;
    },

    confirmEx: function(aDialogTitle, aText, aButtonFlags,
                        aButton0Title, aButton1Title, aButton2Title,
                        aCheckMsg, aCheckState)
    {
      this._toggleModalState();
      promptState = {method: "confirmCheck",
                     parent: this.domWindow,
                     title: aDialogTitle,
                     msg: aText,
                     checkMsg: aCheckMsg,
                     checkState: aCheckState
      };

      if (aCheckMsg != null)
        SpecialPowers.wrap(aCheckState).value = true;

      return 0;
    },

    prompt: function(aDialogTitle, aText, aValue, aCheckMsg,
                     aCheckState)
    {
      this._toggleModalState();
      promptState = {method: "prompt",
                     parent: this.domWindow,
                     title: aDialogTitle,
                     msg: aText,
                     checkMsg: aCheckMsg,
                     checkState: aCheckState
      };

      if (aCheckMsg != null)
        SpecialPowers.wrap(aCheckState).value = true;

      return true;
    },
  };


  // Override the prompt service with our own so that we can test
  // modal dialogs

  function MockPromptService()
  {
  }

  MockPromptService.prototype = {
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptFactory, Ci.nsIPromptService]),

    getPrompt: function(aDOMWindow, aIID)
    {
        return new MockPrompt(aDOMWindow);
    },

    alert: function(aParent, aDialogTitle, aText)
    {
      var prompt = new MockPrompt(aParent);
      return prompt.alert(aDialogTitle, aText);
    },

    alertCheck: function(aParent, aDialogTitle, aText, aCheckMsg, aCheckState)
    {
      var prompt = new MockPrompt(aParent);
      return prompt.alertCheck(aDialogTitle, aText, aCheckMsg, aCheckState);
    },

    confirm: function(aParent, aDialogTitle, aText)
    {
      var prompt = new MockPrompt(aParent);
      return prompt.confirm(aDialogTitle, aText);
    },

    confirmCheck: function(aParent, aDialogTitle, aText, aCheckMsg,
                           aCheckState)
    {
      var prompt = new MockPrompt(aParent);
      return prompt.confirmCheck(aDialogTitle, aText, aCheckMsg, aCheckState);
    },

    confirmEx: function(aParent, aDialogTitle, aText, aButtonFlags,
                        aButton0Title, aButton1Title, aButton2Title,
                        aCheckMsg, aCheckState)
    {
      var prompt = new MockPrompt(aParent);
      return prompt.confirmEx(aDialogTitle, aText, aButtonFlags,
                        aButton0Title, aButton1Title, aButton2Title,
                        aCheckMsg, aCheckState);
    },

    prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg,
                     aCheckState)
    {
      var prompt = new MockPrompt(aParent);
      return prompt.prompt(aDialogTitle, aText, aValue, aCheckMsg, aCheckState);
    },

  };

  mockPromptServiceRegisterer =
    new MockObjectRegisterer("@mozilla.org/embedcomp/prompt-service;1",
                             MockPromptService);
  mockPromptFactoryRegisterer =
    new MockObjectRegisterer("@mozilla.org/prompter;1",
                             MockPromptService);

  mockPromptServiceRegisterer.register();
  mockPromptFactoryRegisterer.register();
};

var expectedState;

function runtests()
{
  SpecialPowers.pushPrefEnv({'set': [["dom.successive_dialog_time_limit", 3]]},
                            runtestsInner);
}

function runtestsInner()
{
  registerMockPromptService();

  // Test that alert() works normally and then gets blocked on the
  // second call.
  w = window.open();
  w.alert("alert message 1");
  is (promptState.method, "alert", "Wrong prompt method called");
  is (promptState.parent, w, "Wrong alert parent");
  is (promptState.msg, "alert message 1", "Wrong alert message");
  promptState = void(0);

  w.alert("alert message 2");
  is (promptState.method, "alertCheck", "Wrong prompt method called");
  is (promptState.parent, w, "Wrong alert parent");
  is (promptState.msg, "alert message 2", "Wrong alert message");
  promptState = void(0);

  try {
    w.alert("alert message 3");
  } catch(e) {
    is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
  }

  is (promptState, void(0), "Wrong prompt state after blocked alert()");

  w.close();

  // Test that confirm() works normally and then gets blocked on the
  // second call.
  w = window.open();
  w.confirm("confirm message 1");
  is (promptState.method, "confirm", "Wrong prompt method called");
  is (promptState.parent, w, "Wrong confirm parent");
  is (promptState.msg, "confirm message 1", "Wrong confirm message");
  promptState = void(0);

  w.confirm("confirm message 2");
  is (promptState.method, "confirmCheck", "Wrong prompt method called");
  is (promptState.parent, w, "Wrong confirm parent");
  is (promptState.msg, "confirm message 2", "Wrong confirm message");
  promptState = void(0);

  try {
    w.confirm("confirm message 3");
  } catch(e) {
    is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
  }

  is (promptState, void(0), "Wrong prompt state after blocked confirm()");

  w.close();

  // Test that prompt() works normally and then gets blocked on the
  // second call.
  w = window.open();
  w.prompt("prompt message 1");
  is (promptState.method, "prompt", "Wrong prompt method called");
  is (promptState.parent, w, "Wrong prompt parent");
  is (promptState.msg, "prompt message 1", "Wrong prompt message");
  is (promptState.checkMsg, null, "Wrong dialog value");
  promptState = void(0);

  w.prompt("prompt message 2");
  is (promptState.method, "prompt", "Wrong prompt method called");
  is (promptState.parent, w, "Wrong prompt parent");
  is (promptState.msg, "prompt message 2", "Wrong prompt message");
  is (promptState.checkMsg, "Prevent this page from creating additional dialogs", "Wrong dialog value");
  promptState = void(0);

  try {
    w.prompt("prompt message 3");
  } catch(e) {
    is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
  }

  is (promptState, void(0), "Wrong prompt state after blocked prompt()");

  w.close();

  // Test that showModalDialog() works normally and then gets blocked
  // on the second call.
  if (window.showModalDialog) {
    w = window.open();
    w.showModalDialog("data:text/html,%3Cscript>window.close();%3C/script>")
    is (promptState, void(0), "Wrong prompt state");

    try {
      w.showModalDialog("data:text/html,%3Cscript>window.close();%3C/script>")
      ok(false, "showModalDialog call should throw an exception");
    } catch(e) {
      is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
    }
    is (promptState.method, "confirm", "Wrong prompt method called");
    is (promptState.parent, w, "Wrong confirm parent");
    is (promptState.msg, "Prevent this page from creating additional dialogs",
        "Wrong confirm message");
    promptState = void(0);

    w.close();
  }

  mockPromptFactoryRegisterer.unregister();
  mockPromptServiceRegisterer.unregister();

  SimpleTest.finish();
}

</script>
</body>
</html>