/*
 * 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 boolean isIE8Or9 = false;
  private static final int TEST_DELAY = 10000;

  /**
   * Check if the browser is IE8,9.
   *
   * @return <code>true</code> if the browser is IE8, IE9
   *         <code>false</code> any other browser
   */
  static boolean isIE8Or9() {
    if (!browserChecked) {
      isIE8Or9 = isIE8Or9Impl();
      browserChecked = true;
    }
    return isIE8Or9;
  }

  private static native boolean isIE8Or9Impl() /*-{
    return /msie/i.test(navigator.userAgent) && $doc.documentMode >= 8 && $doc.documentMode <= 9;
  }-*/;

  @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);
    if (!isIE8Or9()) {
      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);
    if (!isIE8Or9()) {
      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));
    if (!isIE8Or9()) {
      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() {
    if (isIE8Or9()) {
      return;
    }

    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));
                if (!isIE8Or9()) {
                  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));
                    if (!isIE8Or9()) {
                      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);
                if (!isIE8Or9()) {
                  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);
                    if (!isIE8Or9()) {
                      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);
                    if (!isIE8Or9()) {
                      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() {
    if (isIE8Or9()) {
      // IE doesn't support CSP.
      return;
    }
    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));
                    if (!isIE8Or9()) {
                      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() {
    if (isIE8Or9()) {
      // IE doesn't support CSP.
      return;
    }
    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));
                    if (!isIE8Or9()) {
                      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;
  }-*/;
}
