/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.gwt.core.client;

import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.ScriptInjector.FromString;
import com.google.gwt.junit.client.GWTTestCase;

/**
 * Tests for {@link ScriptInjector}
 */
public class ScriptInjectorTest extends GWTTestCase {
  private static boolean browserChecked = false;
  private static final int CHECK_DELAY = 100;

  private static final int TEST_DELAY = 10000;

  @Override
  public String getModuleName() {
    return "com.google.gwt.core.Core";
  }

  /**
   * Install a script in the same window as GWT.
   */
  public void testInjectDirectThisWindow() {
    delayTestFinish(TEST_DELAY);
    String scriptBody = "__ti1_var__ = 1;";
    assertFalse(nativeTest1Worked());
    new FromString(scriptBody).inject();
    boolean worked = nativeTest1Worked();
    JavaScriptObject scriptElement = findScriptTextInThisWindow(scriptBody);
    cleanupThisWindow("__ti1_var__", scriptElement);
    assertFalse("cleanup failed", nativeTest1Worked());
    assertTrue("__ti1_var not set in this window", worked);
    assertNull("script element 1 not removed by injection", scriptElement);
    finishTest();
  }

  /**
   * Install a script in the top window.
   */
  public void testInjectDirectTopWindow() {
    String scriptBody = "__ti2_var__ = 2;";
    assertFalse(nativeTest2Worked());
    ScriptInjector.fromString(scriptBody).setWindow(ScriptInjector.TOP_WINDOW).inject();
    boolean worked = nativeTest2Worked();
    JavaScriptObject scriptElement = findScriptTextInTopWindow(scriptBody);
    cleanupTopWindow("__ti2_var__", scriptElement);
    assertTrue("__ti2_var not set in top window", worked);
    assertNull("script element 2 not removed by injection", scriptElement);
  }

  /**
   * Install a script in the same window as GWT, turn off the tag removal.
   */
  public void testInjectDirectWithoutRemoveTag() {
    assertFalse(nativeTest3Worked());
    String scriptBody = "__ti3_var__ = 3;";
    new FromString(scriptBody).setRemoveTag(false).inject();
    boolean worked = nativeTest3Worked();
    JavaScriptObject scriptElement = findScriptTextInThisWindow(scriptBody);
    // Since we are not in the top window, there is no nonce.
    assertNull(nativeGetScriptNonce(scriptElement));
    cleanupThisWindow("__ti3_var__", scriptElement);
    assertFalse("cleanup failed", nativeTest3Worked());
    assertTrue(worked);
    assertNotNull("script element 3 should have been left in DOM", scriptElement);
  }

  /**
   * Inject an absolute URL on this window.
   */
  public void testInjectUrlAbsolute() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = GWT.getModuleBaseForStaticFiles() + "script_injector_test_absolute.js";
    assertFalse(nativeInjectUrlAbsoluteWorked());
    ScriptInjector.fromUrl(scriptUrl).setCallback(new Callback<Void, Exception>() {

      @Override
      public void onFailure(Exception reason) {
        assertNotNull(reason);
        fail("Injection failed: " + reason.toString());
      }

      @Override
      public void onSuccess(Void result) {
        assertTrue(nativeInjectUrlAbsoluteWorked());
        finishTest();
      }

    }).inject();
  }

  /**
   * Inject an absolute URL on the top level window.
   */
  public void testInjectUrlAbsoluteTop() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = GWT.getModuleBaseForStaticFiles() + "script_injector_test_absolute_top.js";
    assertFalse(nativeAbsoluteTopUrlIsLoaded());
    ScriptInjector.fromUrl(scriptUrl).setWindow(ScriptInjector.TOP_WINDOW).setCallback(
        new Callback<Void, Exception>() {

          @Override
          public void onFailure(Exception reason) {
            assertNotNull(reason);
            fail("Injection failed: " + reason.toString());
          }

          @Override
          public void onSuccess(Void result) {
            assertTrue(nativeAbsoluteTopUrlIsLoaded());
            finishTest();
          }
        }).inject();
  }

  /**
   * This script injection should fail and fire the onFailure callback.
   *
   * <p>Note, the onerror mechanism used to trigger the failure event is a modern browser feature.
   *
   * <p>On IE, the script.onerror tag has been documented, but busted for <a href=
   * "http://stackoverflow.com/questions/2027849/how-to-trigger-script-onerror-in-internet-explorer/2032014#2032014"
   * >aeons</a>.
   */
  public void testInjectUrlFail() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = "uNkNoWn_sCrIpT_404.js";
    JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl).setCallback(new Callback<Void, Exception>() {

          @Override
          public void onFailure(Exception reason) {
            assertNotNull(reason);
            finishTest();
          }

          @Override
          public void onSuccess(Void result) {
            fail("Injection unexpectedly succeeded.");
          }
        }).inject();
    assertNotNull(injectedElement);
  }

  /**
   * Install a script in the same window as GWT by URL
   */
  public void testInjectUrlThisWindow() {
    this.delayTestFinish(TEST_DELAY);
    final String scriptUrl = "script_injector_test4.js";
    assertFalse(nativeTest4Worked());
    final JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl).setRemoveTag(false).inject();

    // We'll check using a callback in another test. This test will poll to see
    // that the script had an effect.
    Scheduler.get()
        .scheduleFixedDelay(
            new RepeatingCommand() {
              int numLoops = 0;

              @Override
              public boolean execute() {
                numLoops++;
                boolean worked = nativeTest4Worked();
                if (!worked && (numLoops * CHECK_DELAY < TEST_DELAY)) {
                  return true;
                }
                JavaScriptObject scriptElement = findScriptUrlInThisWindow(scriptUrl);
                // Since we are not in the top window, there is no nonce.
                assertNull(nativeGetScriptNonce(scriptElement));
                cleanupThisWindow("__ti4_var__", scriptElement);
                assertFalse("cleanup failed", nativeTest4Worked());
                assertTrue("__ti4_var not set in this window", worked);
                assertNotNull("script element 4 not found", scriptElement);
                assertEquals(injectedElement, scriptElement);
                finishTest();

                // never reached
                return false;
              }
            },
            CHECK_DELAY);
    assertNotNull(injectedElement);
  }

  /**
   * Install a script in the same window as GWT by URL
   */
  public void testInjectUrlThisWindowCallback() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = "script_injector_test5.js";
    assertFalse(nativeTest5Worked());
    JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl)
            .setRemoveTag(false)
            .setCallback(
                new Callback<Void, Exception>() {
                  @Override
                  public void onFailure(Exception reason) {
                    assertNotNull(reason);
                    fail("Injection failed: " + reason.toString());
                  }

                  @Override
                  public void onSuccess(Void result) {
                    boolean worked = nativeTest5Worked();
                    JavaScriptObject scriptElement = findScriptUrlInThisWindow(scriptUrl);
                    // Since we are not in the top window, there is no nonce.
                    assertNull(nativeGetScriptNonce(scriptElement));
                    cleanupThisWindow("__ti5_var__", scriptElement);
                    assertFalse("cleanup failed", nativeTest5Worked());
                    assertTrue("__ti5_var not set in this window", worked);
                    assertNotNull("script element 5 not found", scriptElement);
                    finishTest();
                  }
                })
            .inject();
    assertNotNull(injectedElement);
  }

  /**
   * Install a script in the top window by URL
   */
  public void testInjectUrlTopWindow() {
    final String scriptUrl = "script_injector_test6.js";
    assertFalse(nativeTest6Worked());
    JavaScriptObject injectedElement = ScriptInjector.fromUrl(scriptUrl).setRemoveTag(false)
        .setWindow(ScriptInjector.TOP_WINDOW).inject();
    // We'll check using a callback in another test. This test will poll to see
    // that the script had an effect.
    Scheduler.get()
        .scheduleFixedDelay(
            new RepeatingCommand() {
              int numLoops = 0;

              @Override
              public boolean execute() {
                numLoops++;

                boolean worked = nativeTest6Worked();
                if (!worked && (numLoops * CHECK_DELAY < TEST_DELAY)) {
                  return true;
                }
                JavaScriptObject scriptElement = findScriptUrlInTopWindow(scriptUrl);
                assertDefaultNonce(scriptElement);
                cleanupTopWindow("__ti6_var__", scriptElement);
                assertFalse("cleanup failed", nativeTest6Worked());
                assertTrue("__ti6_var not set in top window", worked);
                assertNotNull("script element 6 not found", scriptElement);
                finishTest();
                // never reached
                return false;
              }
            },
            CHECK_DELAY);
    assertNotNull(injectedElement);
  }

  /**
   * Install a script in the top window by URL
   */
  public void testInjectUrlTopWindowCallback() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = "script_injector_test7.js";
    assertFalse(nativeTest7Worked());
    JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl)
            .setRemoveTag(false)
            .setWindow(ScriptInjector.TOP_WINDOW)
            .setCallback(
                new Callback<Void, Exception>() {

                  @Override
                  public void onFailure(Exception reason) {
                    assertNotNull(reason);
                    fail("Injection failed: " + reason.toString());
                  }

                  @Override
                  public void onSuccess(Void result) {
                    boolean worked = nativeTest7Worked();
                    JavaScriptObject scriptElement = findScriptUrlInTopWindow(scriptUrl);
                    assertDefaultNonce(scriptElement);
                    cleanupTopWindow("__ti7_var__", scriptElement);
                    assertFalse("cleanup failed", nativeTest7Worked());
                    assertTrue("__ti7_var not set in top window", worked);
                    assertNotNull("script element 7 not found", scriptElement);
                    finishTest();
                  }
                })
            .inject();
    assertNotNull(injectedElement);
  }

  /**
   * Tests encoding of the injected script (UTF-8)
   */
  public void testInjectUrlUtf8() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = "script_injector_test_utf8.js";
    assertEquals("", nativeGetTestUtf8Var());
    JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl)
            .setRemoveTag(false)
            .setWindow(ScriptInjector.TOP_WINDOW)
            .setCallback(
                new Callback<Void, Exception>() {

                  @Override
                  public void onFailure(Exception reason) {
                    assertNotNull(reason);
                    fail("Injection failed: " + reason.toString());
                  }

                  @Override
                  public void onSuccess(Void result) {
                    String testVar = nativeGetTestUtf8Var();
                    JavaScriptObject scriptElement = findScriptUrlInTopWindow(scriptUrl);
                    assertDefaultNonce(scriptElement);
                    cleanupTopWindow("__ti_utf8_var__", scriptElement);
                    assertEquals("cleanup failed", "", nativeGetTestUtf8Var());
                    assertEquals("__ti_utf8_var not set in top window", "à", testVar);
                    assertNotNull("script element not found", scriptElement);
                    finishTest();
                  }
                })
            .inject();
    assertNotNull(injectedElement);
  }

  public void testInjectUrlTopWindowNoncePropegated() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = "script_injector_test9.js";
    final String nonceScriptUrl = "script_injector_test9_nonce.js";
    final String nonce = "IAlwaysGetTheShemp";
    final JavaScriptObject noncedScript =
        nativeAddScriptWithNonceToWindow(nativeTopWindow(), nonce, nonceScriptUrl);
    assertEquals(nonce, nativeGetScriptNonce(noncedScript));
    assertFalse(nativeTest9Worked());
    JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl)
            .setRemoveTag(false)
            .setWindow(ScriptInjector.TOP_WINDOW)
            .setCallback(
                new Callback<Void, Exception>() {

                  @Override
                  public void onFailure(Exception reason) {
                    assertNotNull(reason);
                    fail("Injection failed: " + reason.toString());
                  }

                  @Override
                  public void onSuccess(Void result) {
                    boolean worked = nativeTest9Worked();
                    JavaScriptObject scriptElement = findScriptUrlInTopWindow(scriptUrl);
                    assertEquals(nonce, nativeGetScriptNonce(scriptElement));
                    cleanupTopWindow("__ti9_var__", scriptElement);
                    cleanupTopWindow("__ti9_nonce_var__", noncedScript);
                    assertFalse("cleanup failed", nativeTest9Worked());
                    assertTrue("__ti9_var not set in top window", worked);
                    assertNotNull("script element 9 not found", scriptElement);
                    finishTest();
                  }
                })
            .inject();
    assertNotNull(injectedElement);
  }

  public void testInjectUrlThisWindowNoncePropegated() {
    delayTestFinish(TEST_DELAY);
    final String scriptUrl = "script_injector_test10.js";
    final String nonceScriptUrl = "script_injector_test10_nonce.js";
    final String nonce = "ANearbyRoosterIsInHighDef";
    final JavaScriptObject noncedScript =
        nativeAddScriptWithNonceToWindow(nativeThisWindow(), nonce, nonceScriptUrl);
    assertEquals(nonce, nativeGetScriptNonce(noncedScript));
    assertFalse(nativeTest10Worked());
    JavaScriptObject injectedElement =
        ScriptInjector.fromUrl(scriptUrl)
            .setRemoveTag(false)
            .setCallback(
                new Callback<Void, Exception>() {

                  @Override
                  public void onFailure(Exception reason) {
                    assertNotNull(reason);
                    fail("Injection failed: " + reason.toString());
                  }

                  @Override
                  public void onSuccess(Void result) {
                    boolean worked = nativeTest10Worked();
                    JavaScriptObject scriptElement = findScriptUrlInThisWindow(scriptUrl);
                    assertEquals(nonce, nativeGetScriptNonce(scriptElement));
                    cleanupThisWindow("__ti10_var__", scriptElement);
                    cleanupThisWindow("__ti10_nonce_var__", noncedScript);
                    assertFalse("cleanup failed", nativeTest10Worked());
                    assertTrue("__ti10_var not set in top window", worked);
                    assertNotNull("script element 10 not found", scriptElement);
                    finishTest();
                  }
                })
            .inject();
    assertNotNull(injectedElement);
  }

  private void cleanupThisWindow(String property, JavaScriptObject scriptElement) {
    cleanupWindow(nativeThisWindow(), property, scriptElement);
  }

  private void cleanupTopWindow(String property, JavaScriptObject scriptElement) {
    cleanupWindow(nativeTopWindow(), property, scriptElement);
  }

  private native void cleanupWindow(JavaScriptObject wnd, String property,
      JavaScriptObject scriptElement) /*-{
    delete wnd[property];
    if (scriptElement) {
      scriptElement.parentNode.removeChild(scriptElement);
    }
  }-*/;

  private void assertDefaultNonce(JavaScriptObject scriptElement) {
    assertEquals(
        "Expected script to have the default nonce value",
        "gwt-nonce",
        nativeGetScriptNonce(scriptElement));
  }

  private native JavaScriptObject nativeAddScriptWithNonceToWindow(
      JavaScriptObject wnd, String nonce, String scriptUrl) /*-{
    var scriptToAdd = wnd.document.createElement('script');
    scriptToAdd.setAttribute('nonce', nonce);
    scriptToAdd.src = scriptUrl;
    var head = wnd.document.head || wnd.document.getElementsByTagName("head")[0];
    head.insertBefore(scriptToAdd, head.firstChild);
    return scriptToAdd;
  }-*/;

  private JavaScriptObject findScriptTextInThisWindow(String text) {
    return nativeFindScriptText(nativeThisWindow(), text);
  }

  private JavaScriptObject findScriptTextInTopWindow(String text) {
    return nativeFindScriptText(nativeTopWindow(), text);
  }

  private JavaScriptObject findScriptUrlInThisWindow(String url) {
    return nativeFindScriptUrl(nativeThisWindow(), url);
  }

  private JavaScriptObject findScriptUrlInTopWindow(String url) {
    return nativeFindScriptUrl(nativeTopWindow(), url);
  }

  private native boolean nativeAbsoluteTopUrlIsLoaded() /*-{
    return !!$wnd["__tiabsolutetop_var__"] && $wnd["__tiabsolutetop_var__"] == 102;
  }-*/;

  private native JavaScriptObject nativeFindScriptText(JavaScriptObject wnd, String text) /*-{
    var scripts = wnd.document.getElementsByTagName("script");
    for ( var i = 0; i < scripts.length; ++i) {
      if (scripts[i].text.match("^" + text)) {
        return scripts[i];
      }
    }
    return null;
  }-*/;

  /**
   * Won't work for all urls, uses a regular expression match
   */
  private native JavaScriptObject nativeFindScriptUrl(JavaScriptObject wnd, String url) /*-{
    var scripts = wnd.document.getElementsByTagName("script");
    for ( var i = 0; i < scripts.length; ++i) {
      if (scripts[i].src.match(url)) {
        return scripts[i];
      }
    }
    return null;
  }-*/;

  private native String nativeGetScriptNonce(JavaScriptObject scriptElement) /*-{
    return scriptElement['nonce'] || scriptElement.getAttribute('nonce');
  }-*/;

  private native boolean nativeInjectUrlAbsoluteWorked() /*-{
    return !!window["__tiabsolute_var__"] && window["__tiabsolute_var__"] == 101;
  }-*/;

  private native boolean nativeTest1Worked() /*-{
    return !!window["__ti1_var__"] && window["__ti1_var__"] == 1;
  }-*/;

  private native boolean nativeTest2Worked() /*-{
    return !!$wnd["__ti2_var__"] && $wnd["__ti2_var__"] == 2;
  }-*/;

  private native boolean nativeTest3Worked() /*-{
    return !!window["__ti3_var__"] && window["__ti3_var__"] == 3;
  }-*/;

  private native boolean nativeTest4Worked() /*-{
    return !!window["__ti4_var__"] && window["__ti4_var__"] == 4;
  }-*/;

  private native boolean nativeTest5Worked() /*-{
    return !!window["__ti5_var__"] && window["__ti5_var__"] == 5;
  }-*/;

  private native boolean nativeTest6Worked() /*-{
    return !!$wnd["__ti6_var__"] && $wnd["__ti6_var__"] == 6;
  }-*/;

  private native boolean nativeTest7Worked() /*-{
    return !!$wnd["__ti7_var__"] && $wnd["__ti7_var__"] == 7;
  }-*/;

  private native String nativeGetTestUtf8Var() /*-{
    return $wnd["__ti_utf8_var__"] || "";
  }-*/;

  private native boolean nativeTest9Worked() /*-{
    return !!$wnd["__ti9_var__"] && $wnd["__ti9_var__"] == 9;
  }-*/;

  private native boolean nativeTest10Worked() /*-{
    return !!window["__ti10_var__"] && window["__ti10_var__"] == 10;
  }-*/;

  private native JavaScriptObject nativeThisWindow() /*-{
    return window;
  }-*/;

  private native JavaScriptObject nativeTopWindow() /*-{
    return $wnd;
  }-*/;
}
