// Copyright (C) 2009 The Android Open Source Project
//
// 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.gwtexpui.user.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;

/**
 * User agent feature tests we don't create permutations for.
 * <p>
 * Some features aren't worth creating full permutations in GWT for, as each new
 * boolean permutation (only two settings) doubles the compile time required. If
 * the setting only affects a couple of lines of JavaScript code, the slightly
 * larger cache files for user agents that lack the functionality requested is
 * trivial compared to the time developers lose building their application.
 */
public class UserAgent {
  private static boolean jsClip = guessJavaScriptClipboard();

  public static boolean hasJavaScriptClipboard() {
    return jsClip;
  }

  public static void disableJavaScriptClipboard() {
    jsClip = false;
  }

  private static native boolean nativeHasCopy()
  /*-{ return $doc['queryCommandSupported'] && $doc.queryCommandSupported('copy') }-*/;

  private static boolean guessJavaScriptClipboard() {
    String ua = Window.Navigator.getUserAgent();
    int chrome = major(ua, "Chrome/");
    if (chrome > 0) {
      return 42 <= chrome;
    }

    int ff = major(ua, "Firefox/");
    if (ff > 0) {
      return 41 <= ff;
    }

    int opera = major(ua, "OPR/");
    if (opera > 0) {
      return 29 <= opera;
    }

    int msie = major(ua, "MSIE ");
    if (msie > 0) {
      return 9 <= msie;
    }

    if (nativeHasCopy()) {
      // Firefox 39.0 lies and says it supports copy, then fails.
      // So we try this after the browser specific test above.
      return true;
    }

    // Safari is not planning to support document.execCommand('copy').
    // Assume the browser does not have the feature.
    return false;
  }

  private static int major(String ua, String product) {
    int entry = ua.indexOf(product);
    if (entry >= 0) {
      String s = ua.substring(entry + product.length());
      String p = s.split("[ /;,.)]", 2)[0];
      try {
        return Integer.parseInt(p);
      } catch (NumberFormatException nan) {
        // Ignored
      }
    }
    return -1;
  }

  public static class Flash {
    private static boolean checked;
    private static boolean installed;

    /**
     * Does the browser have ShockwaveFlash plugin installed?
     * <p>
     * This method may still return true if the user has disabled Flash or set
     * the plugin to "click to run".
     */
    public static boolean isInstalled() {
      if (!checked) {
        installed = hasFlash();
        checked = true;
      }
      return installed;
    }

    private static native boolean hasFlash()
    /*-{
      if (navigator.plugins && navigator.plugins.length) {
        if (navigator.plugins['Shockwave Flash'])     return true;
        if (navigator.plugins['Shockwave Flash 2.0']) return true;

      } else if (navigator.mimeTypes && navigator.mimeTypes.length) {
        var mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
        if (mimeType && mimeType.enabledPlugin) return true;

      } else {
        try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7'); return true; } catch (e) {}
        try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6'); return true; } catch (e) {}
        try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash');   return true; } catch (e) {}
      }
      return false;
    }-*/;
  }

  /**
   * Test for and disallow running this application in an &lt;iframe&gt;.
   * <p>
   * If the application is running within an iframe this method requests a
   * browser generated redirect to pop the application out of the iframe into
   * the top level window, and then aborts execution by throwing an exception.
   * This is call should be placed early within the module's onLoad() method,
   * before any real UI can be initialized that an attacking site could try to
   * snip out and present in a confusing context.
   * <p>
   * If the break out works, execution will restart automatically in a proper
   * top level window, where the script has full control over the display. If
   * the break out fails, execution will abort and stop immediately, preventing
   * UI widgets from being created, leaving the user with an empty frame.
   */
  public static void assertNotInIFrame() {
    if (GWT.isScript() && amInsideIFrame()) {
      bustOutOfIFrame(Window.Location.getHref());
      throw new RuntimeException();
    }
  }

  private static native boolean amInsideIFrame()
  /*-{ return top.location != $wnd.location; }-*/;

  private static native void bustOutOfIFrame(String newloc)
  /*-{ top.location.href = newloc }-*/;

  private UserAgent() {
  }
}
