// 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) {
      }
    }
    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() {
  }
}
