Revision: 10305
Author:   jasonh...@google.com
Date:     Thu Jun  9 04:36:38 2011
Log:      HTML5 Geolocation support in GWT

Review at http://gwt-code-reviews.appspot.com/1451811

Review by: jlaba...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=10305

Added:
 /trunk/user/src/com/google/gwt/geolocation
 /trunk/user/src/com/google/gwt/geolocation/Geolocation.gwt.xml
 /trunk/user/src/com/google/gwt/geolocation/client
 /trunk/user/src/com/google/gwt/geolocation/client/Geolocation.java
 /trunk/user/src/com/google/gwt/geolocation/client/Position.java
 /trunk/user/src/com/google/gwt/geolocation/client/PositionError.java
 /trunk/user/src/com/google/gwt/geolocation/client/PositionImpl.java
 /trunk/user/src/com/google/gwt/geolocation/client/package-info.java
 /trunk/user/test/com/google/gwt/geolocation
 /trunk/user/test/com/google/gwt/geolocation/GeolocationSuite.java
 /trunk/user/test/com/google/gwt/geolocation/client
 /trunk/user/test/com/google/gwt/geolocation/client/GeolocationTest.java
Modified:
 /trunk/user/src/com/google/gwt/user/User.gwt.xml

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/geolocation/Geolocation.gwt.xml Thu Jun 9 04:36:38 2011
@@ -0,0 +1,36 @@
+<!-- --> +<!-- 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 --> +<!-- 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. License for the specific language governing permissions and --> +<!-- limitations under the License. -->
+
+<module>
+  <inherits name="com.google.gwt.core.Core" />
+  <inherits name="com.google.gwt.user.UserAgent" />
+
+  <!-- Define the Geolocation support property. -->
+  <define-property name="geolocationSupport" values="maybe,no" />
+
+  <!-- Set the property to maybe -->
+  <set-property name="geolocationSupport" value="maybe" />
+
+  <!-- Older browsers do not support Geolocation -->
+  <set-property name="geolocationSupport" value="no">
+    <any>
+      <when-property-is name="user.agent" value="ie6" />
+    </any>
+  </set-property>
+
+ <replace-with class="com.google.gwt.geolocation.client.Geolocation.GeolocationSupportDetectorNo"> + <when-type-is class="com.google.gwt.geolocation.client.Geolocation.GeolocationSupportDetector" />
+    <when-property-is name="geolocationSupport" value="no" />
+  </replace-with>
+</module>
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/geolocation/client/Geolocation.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,301 @@
+/*
+ * 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.geolocation.client;
+
+import com.google.gwt.core.client.Callback;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.dom.client.PartialSupport;
+
+/**
+ * Implements the HTML5 Geolocation interface.
+ *
+ * <p>
+ * You can obtain a user's position by first calling
+ * <code>Geolocation.getIfSupported()</code>
+ * </p>
+ *
+ * <p>
+ * Once you have a <code>Geolocation</code>, you can request the user's current
+ * position by calling {@link #getCurrentPosition(Callback)} or
+ * {@link #watchPosition(Callback)}.
+ * </p>
+ *
+ * <p>
+ * The first time an application requests the user's position, the browser will + * prompt the user for permission. If the user grants permission, the browser
+ * will locate the user and report it back to your application. If the user
+ * declines permission, the callback's {@link Callback#onFailure(Object)} method
+ * will be called with a {@link PositionError} with its code set to
+ * {@link PositionError#PERMISSION_DENIED}.
+ * </p>
+ *
+ * <p>
+ * <span style="color:red;">Experimental API: This API is still under
+ * development and is subject to change.</span>
+ *
+ * <p>
+ * This may not be supported on all browsers.
+ * </p>
+ *
+ * @see <a href="http://www.w3.org/TR/geolocation-API/";>W3C Geolocation API</a> + * @see <a href="http://diveintohtml5.org/geolocation.html";>Dive Into HTML5 -
+ *      Geolocation</a>
+ */
+@PartialSupport
+public class Geolocation {
+
+  private static GeolocationSupportDetector detector;
+  private static Geolocation impl;
+
+  /**
+   * Detector for browser support for Geolocation.
+   */
+  private static class GeolocationSupportDetector {
+
+    private static native boolean detectSupport() /*-{
+      return !!$wnd.navigator.geolocation;
+    }-*/;
+
+    private boolean supported = detectSupport();
+
+    public boolean isSupported() {
+      return supported;
+    }
+  }
+
+  /**
+   * Detector for browsers that do not support Geolocation.
+   */
+  @SuppressWarnings("unused")
+ private static class GeolocationSupportDetectorNo extends GeolocationSupportDetector {
+    @Override
+    public boolean isSupported() {
+      return false;
+    }
+  }
+
+  /**
+   * Additional options for receiving the user's location.
+   */
+  public static class PositionOptions {
+    private boolean enableHighAccuracy = false;
+    private int timeout = -1;
+    private int maximumAge = 0;
+
+    /**
+ * Sets whether or not the application will request a more accurate position
+     * from the browser.
+     *
+     * <p>
+ * If the browser supports this option, the user will be prompted to grant
+     * permission to this application, even if permission to get the user's
+     * (less accurate) position has already been granted.</p>
+     *
+     * <p>
+     * Requesting high accuracy may be slower, or not supported at all,
+     * depending on the browser.
+     * </p>
+     *
+     * <p>
+     * By default this is <code>false</code>
+     * </p>
+     */
+    public PositionOptions setHighAccuracyEnabled(boolean enabled) {
+      this.enableHighAccuracy = enabled;
+      return this;
+    }
+
+    /**
+     * Allows the browser to return a position immediately with a cached
+     * position. The maximum age is then the oldest acceptable cached
+ * position. If no acceptable cached position is found, the browser will
+     * locate the user and cache and return the position.
+     *
+     * <p>
+ * By default this is 0, which means that the position cache will not be
+     * used.
+     * </p>
+     */
+    public PositionOptions setMaximumAge(int maximumAge) {
+      this.maximumAge = maximumAge;
+      return this;
+    }
+
+    /**
+ * Sets the amount of time (in milliseconds) that the application is willing + * to wait before getting the user's position. If a request for position
+     * takes more than this amount of time, an error will result.
+     *
+     * <p>
+     * By default this is -1, which means there is no application-specified
+     * timeout.
+     * </p>
+     */
+    public PositionOptions setTimeout(int timeout) {
+      this.timeout = timeout;
+      return this;
+    }
+  }
+
+  /**
+ * Returns a {@link Geolocation} if the browser supports this feature, and
+   * <code>null</code> otherwise.
+   */
+  public static Geolocation getIfSupported() {
+    if (!isSupported()) {
+      return null;
+    } else {
+      if (impl == null) {
+        impl = new Geolocation();
+      }
+      return impl;
+    }
+  }
+
+  /**
+   * Returns <code>true</code> if the browser supports geolocation.
+   */
+  public static boolean isSupported() {
+    if (detector == null) {
+      detector = GWT.create(GeolocationSupportDetector.class);
+    }
+    return detector.isSupported();
+  }
+
+ private static void handleFailure(Callback<Position, PositionError> callback, int code,
+      String msg) {
+    callback.onFailure(new PositionError(code, msg));
+  }
+
+ private static void handleSuccess(Callback<Position, PositionError> callback, PositionImpl pos) {
+    callback.onSuccess(pos);
+  }
+
+ private static native JavaScriptObject toJso(PositionOptions options) /*-{
+    var opt = {};
+    if (options) {
+ opt.enableHighAccuracy = optio...@com.google.gwt.geolocation.client.Geolocation.PositionOptions::enableHighAccuracy; + opt.maximumAge = optio...@com.google.gwt.geolocation.client.Geolocation.PositionOptions::maximumAge;
+
+ if (optio...@com.google.gwt.geolocation.client.Geolocation.PositionOptions::timeout
0) {
+ opt.timeout = optio...@com.google.gwt.geolocation.client.Geolocation.PositionOptions::timeout;
+      }
+    }
+    return opt;
+  }-*/;
+
+  /**
+   * Should be instantiated by {@link #getIfSupported()}.
+   */
+  protected Geolocation() {
+  }
+
+  /**
+   * Stops watching the user's position.
+   *
+ * @param watchId the ID of a position watch as returned by a previous call to
+   *        {@link #watchPosition(Callback)}.
+   */
+  public native void clearWatch(int watchId) /*-{
+    $wnd.navigator.geolocation.clearWatch(watchId);
+  }-*/;
+
+  /**
+   * Calls the callback with the user's current position.
+   */
+ public void getCurrentPosition(Callback<Position, PositionError> callback) {
+    getCurrentPosition(callback, null);
+  }
+
+  /**
+   * Calls the callback with the user's current position, with additional
+   * options.
+   */
+ public native void getCurrentPosition(Callback<Position, PositionError> callback,
+      PositionOptions options) /*-{
+ var opt = @com.google.gwt.geolocation.client.Geolocation::toJso(*)(options);
+
+    var success = $entry(function(pos) {
+ @com.google.gwt.geolocation.client.Geolocation::handleSuccess(*)(callback, pos);
+    });
+
+    var failure = $entry(function(err) {
+      @com.google.gwt.geolocation.client.Geolocation::handleFailure(*)
+      (callback, err.code, err.message);
+    });
+
+    if (@com.google.gwt.geolocation.client.Geolocation::isSupported()) {
+      $wnd.navigator.geolocation.getCurrentPosition(success, failure, opt);
+    }
+  }-*/;
+
+  /**
+   * Repeatedly calls the given callback with the user's position, as it
+   * changes.
+   *
+   * <p>
+ * The frequency of these updates is entirely up to the browser. There is no
+   * guarantee that updates will be received at any set interval, but are
+ * instead designed to be sent when the user's position changes. This method
+   * should be used instead of polling the user's current position.
+   * </p>
+   *
+   * @return the ID of this watch, which can be passed to
+   *         {@link #clearWatch(int)} to stop watching the user's position.
+   */
+  public int watchPosition(Callback<Position, PositionError> callback) {
+    return watchPosition(callback, null);
+  }
+
+  /**
+   * Repeatedly calls the given callback with the user's position, as it
+   * changes, with additional options.
+   *
+   * <p>
+ * The frequency of these updates is entirely up to the browser. There is no
+   * guarantee that updates will be received at any set interval, but are
+ * instead designed to be sent when the user's position changes. This method
+   * should be used instead of polling the user's current position.
+   * </p>
+   *
+   * <p>
+ * If the browser does not support geolocation, this method will do nothing,
+   * and will return -1.
+   * </p>
+   *
+   * @return the ID of this watch, which can be passed to
+   *         {@link #clearWatch(int)} to stop watching the user's position.
+   */
+ public native int watchPosition(Callback<Position, PositionError> callback,
+      PositionOptions options) /*-{
+ var opt = @com.google.gwt.geolocation.client.Geolocation::toJso(*)(options);
+
+    var success = $entry(function(pos) {
+ @com.google.gwt.geolocation.client.Geolocation::handleSuccess(*)(callback, pos);
+    });
+
+    var failure = $entry(function(err) {
+      @com.google.gwt.geolocation.client.Geolocation::handleFailure(*)
+      (callback, err.code, err.message);
+    });
+
+    if (@com.google.gwt.geolocation.client.Geolocation::isSupported()) {
+      $wnd.navigator.geolocation.watchPosition(success, failure, opt);
+    }
+  }-*/;
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/geolocation/client/Position.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,88 @@
+/*
+ * 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.geolocation.client;
+
+import com.google.gwt.core.client.SingleJsoImpl;
+import com.google.gwt.geolocation.client.PositionImpl.CoordinatesImpl;
+
+/**
+ * Represents information about the user's position as reported by the browser.
+ */
+@SingleJsoImpl(PositionImpl.class)
+public interface Position {
+
+  /**
+   * Returns information about the coordinates reported by the browser.
+   */
+  public Coordinates getCoordinates();
+
+  /**
+   * Returns the time this position was reported by the browser.
+   */
+  public double getTimestamp();
+
+  /**
+   * Represents position reported by the browser.
+   */
+  @SingleJsoImpl(CoordinatesImpl.class)
+  public interface Coordinates {
+
+    /**
+     * Returns the estimated accuracy reported by the browser, in meters.
+     */
+    public double getAccuracy();
+
+    /**
+ * Returns the altitude reported by the browser, in meters, above the <a
+     * href="http://en.wikipedia.org/wiki/Reference_ellipsoid";>reference
+     * ellipsoid</a>, or <code>null</code> if the browser did not report an
+     * altitude.
+     */
+    public Double getAltitude();
+
+    /**
+ * Returns the estimated accuracy of the altitude reported by the browser,
+     * in meters, or <code>null</code> if the browser did not report an
+     * accuracy.
+     */
+    public Double getAltitudeAccuracy();
+
+    /**
+ * Returns the heading, in degrees from due north, reported by the browser, + * based on previous calls to get the user's position, or <code>null</code>
+     * if the browser did not report a heading.
+     */
+    public Double getHeading();
+
+    /**
+     * Returns the decimal latitude reported by the browser.
+     */
+    public double getLatitude();
+
+    /**
+     * Returns the decimal longitude reported by the browser.
+     */
+    public double getLongitude();
+
+    /**
+ * Returns the speed, in meters/second, reported by the browser, based on + * previous calls to get the user's position, or <code>null</code> if the
+     * browser did not report a speed.
+     */
+    public Double getSpeed();
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/geolocation/client/PositionError.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,58 @@
+/*
+ * 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.geolocation.client;
+
+/**
+ * Represents an error that occurred while trying to get the user's current
+ * position.
+ */
+public final class PositionError extends Throwable {
+
+  /**
+   * An unknown error occurred.
+   */
+  public static final int UNKNOWN_ERROR = 0;
+
+  /**
+   * The user declined access to their position to this application.
+   */
+  public static final int PERMISSION_DENIED = 1;
+
+  /**
+   * The browser was unable to locate the user.
+   */
+  public static final int POSITION_UNAVAILABLE = 2;
+
+  /**
+   * The browser was unable to locate the user in enough time.
+   */
+  public static final int TIMEOUT = 3;
+
+  private final int code;
+
+  PositionError(int code, String message) {
+    super(message);
+    this.code = code;
+  }
+
+  /**
+   * Returns the error code associated with this error.
+   */
+  public int getCode() {
+    return code;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/geolocation/client/PositionImpl.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,79 @@
+/*
+ * 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.geolocation.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/**
+ * Real {@link JavaScriptObject} implementation of the {@link Position}.
+ */
+final class PositionImpl extends JavaScriptObject implements Position {
+
+  protected PositionImpl() {
+  }
+
+  @Override
+  public final native Coordinates getCoordinates() /*-{
+    return this.coords;
+  }-*/;
+
+  @Override
+  public final native double getTimestamp() /*-{
+    return this.timestamp;
+  }-*/;
+
+ static final class CoordinatesImpl extends JavaScriptObject implements Coordinates {
+
+    protected CoordinatesImpl() {
+    }
+
+    @Override
+    public final native double getAccuracy() /*-{
+      return this.accuracy;
+    }-*/;
+
+    @Override
+    public final native Double getAltitude() /*-{
+      return this.altitude || null;
+    }-*/;
+
+    @Override
+    public final native Double getAltitudeAccuracy() /*-{
+      return this.altitudeAccuracy || null;
+    }-*/;
+
+    @Override
+    public final native Double getHeading() /*-{
+      return this.heading || null;
+    }-*/;
+
+    @Override
+    public final native double getLatitude() /*-{
+      return this.latitude;
+    }-*/;
+
+    @Override
+    public final native double getLongitude() /*-{
+      return this.longitude;
+    }-*/;
+
+    @Override
+    public final native Double getSpeed() /*-{
+      return this.speed || null;
+    }-*/;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/geolocation/client/package-info.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * <p>
+ * Support for the HTML5 Geolocation API.
+ * </p>
+ */
+@com.google.gwt.util.PreventSpuriousRebuilds
+package com.google.gwt.geolocation.client;
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/geolocation/GeolocationSuite.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,35 @@
+/*
+ * 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.geolocation;
+
+import com.google.gwt.geolocation.client.GeolocationTest;
+import com.google.gwt.junit.tools.GWTTestSuite;
+
+import junit.framework.Test;
+
+/**
+ * Suite for all Geolocation tests.
+ */
+public class GeolocationSuite {
+  public static Test suite() {
+    GWTTestSuite suite = new GWTTestSuite("Geolocation Tests");
+
+    suite.addTestSuite(GeolocationTest.class);
+
+    return suite;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/geolocation/client/GeolocationTest.java Thu Jun 9 04:36:38 2011
@@ -0,0 +1,50 @@
+/*
+ * 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.geolocation.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Tests for {@link Geolocation}.
+ */
+public class GeolocationTest extends GWTTestCase {
+
+  protected Geolocation geolocation;
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.geolocation.Geolocation";
+  }
+
+  @Override
+  protected void gwtSetUp() throws Exception {
+    geolocation = Geolocation.getIfSupported();
+  }
+
+  @Override
+  protected void gwtTearDown() throws Exception {
+    geolocation = null;
+  }
+
+  public void testNullIfUnsupported() {
+    if (!Geolocation.isSupported()) {
+      assertNull(geolocation);
+    } else {
+      assertNotNull(geolocation);
+    }
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/user/User.gwt.xml Mon May 23 11:13:45 2011 +++ /trunk/user/src/com/google/gwt/user/User.gwt.xml Thu Jun 9 04:36:38 2011
@@ -23,6 +23,7 @@
    <inherits name="com.google.gwt.core.Core"/>
    <inherits name="com.google.gwt.editor.Editor" />
    <inherits name="com.google.gwt.event.Event"/>
+   <inherits name="com.google.gwt.geolocation.Geolocation" />
    <inherits name="com.google.gwt.i18n.I18N"/>
    <inherits name="com.google.gwt.layout.Layout"/>
    <inherits name="com.google.gwt.media.Media"/>

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to