Providing Geolocation SPI for masses.
authorJaroslav Tulach <jtulach@netbeans.org>
Wed, 27 Aug 2014 18:45:51 +0200
changeset 846131f27ce1282
parent 841 e673fd71b81b
parent 845 0a7a5a880e6d
child 847 ef06d881d758
Providing Geolocation SPI for masses.
geo/src/main/java/org/netbeans/html/geo/impl/JsG.java
     1.1 --- a/geo/pom.xml	Tue Aug 26 18:38:36 2014 +0200
     1.2 +++ b/geo/pom.xml	Wed Aug 27 18:45:51 2014 +0200
     1.3 @@ -14,7 +14,7 @@
     1.4    <url>http://maven.apache.org</url>
     1.5    <properties>
     1.6      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     1.7 -    <publicPackages>net.java.html.geo</publicPackages>
     1.8 +    <publicPackages>net.java.html.geo,org.netbeans.html.geo.spi</publicPackages>
     1.9    </properties>
    1.10    <build>
    1.11        <plugins>
     2.1 --- a/geo/src/main/java/net/java/html/geo/Position.java	Tue Aug 26 18:38:36 2014 +0200
     2.2 +++ b/geo/src/main/java/net/java/html/geo/Position.java	Wed Aug 27 18:45:51 2014 +0200
     2.3 @@ -42,9 +42,15 @@
     2.4   */
     2.5  package net.java.html.geo;
     2.6  
     2.7 +import java.util.Collections;
     2.8 +import java.util.ServiceLoader;
     2.9  import java.util.logging.Level;
    2.10  import java.util.logging.Logger;
    2.11 -import org.netbeans.html.geo.impl.JsG;
    2.12 +import net.java.html.BrwsrCtx;
    2.13 +import org.netbeans.html.context.spi.Contexts;
    2.14 +import org.netbeans.html.geo.impl.JsGLProvider;
    2.15 +import org.netbeans.html.geo.spi.GLProvider;
    2.16 +import org.netbeans.html.geo.spi.GLProvider.Callback;
    2.17  
    2.18  /** Class that represents a geolocation position provided as a callback
    2.19   * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
    2.20 @@ -59,10 +65,9 @@
    2.21      private final long timestamp;
    2.22      private final Coordinates coords;
    2.23  
    2.24 -    Position(Object position) {
    2.25 -        Object obj = JsG.get(position, "timestamp");
    2.26 -        timestamp = obj instanceof Number ? ((Number)obj).longValue() : 0L;
    2.27 -        coords = new Coordinates(JsG.get(position, "coords"));
    2.28 +    public Position(long timestamp, Coordinates coords) {
    2.29 +        this.timestamp = timestamp;
    2.30 +        this.coords = coords;
    2.31      }
    2.32      
    2.33      /** The actual location of the position.
    2.34 @@ -83,26 +88,22 @@
    2.35       *  Mimics closely <a href="http://www.w3.org/TR/geolocation-API/">
    2.36       * W3C's Geolocation API</a>.
    2.37       */
    2.38 -    public static final class Coordinates {
    2.39 -        private final Object data;
    2.40 -
    2.41 -        Coordinates(Object data) {
    2.42 -            this.data = data;
    2.43 +    public static abstract class Coordinates {
    2.44 +        protected Coordinates() {
    2.45 +            if (!getClass().getName().equals("org.netbeans.html.geo.spi.CoordImpl")) {
    2.46 +                throw new IllegalStateException();
    2.47 +            }
    2.48          }
    2.49          
    2.50          /**
    2.51           * @return geographic coordinate specified in decimal degrees.
    2.52           */
    2.53 -        public double getLatitude() {
    2.54 -            return ((Number)JsG.get(data, "latitude")).doubleValue(); // NOI18N
    2.55 -        }
    2.56 +        public abstract double getLatitude();
    2.57  
    2.58          /**
    2.59           * @return geographic coordinate specified in decimal degrees.
    2.60           */
    2.61 -        public double getLongitude() {
    2.62 -            return ((Number)JsG.get(data, "longitude")).doubleValue(); // NOI18N
    2.63 -        } 
    2.64 +        public abstract double getLongitude();
    2.65  
    2.66          /**
    2.67           * The accuracy attribute denotes the accuracy level of the latitude 
    2.68 @@ -111,18 +112,14 @@
    2.69           * 
    2.70           * @return accuracy in meters
    2.71           */
    2.72 -        public double getAccuracy() {
    2.73 -            return ((Number)JsG.get(data, "accuracy")).doubleValue(); // NOI18N
    2.74 -        }
    2.75 +        public abstract double getAccuracy();
    2.76          
    2.77          /** Denotes the height of the position, specified in meters above the ellipsoid. 
    2.78           * If the implementation cannot provide altitude information, 
    2.79           * the value of this attribute must be null.
    2.80           * @return value in meters, may return null, if the information is not available 
    2.81           */
    2.82 -        public Double getAltitude() {
    2.83 -            return (Double)JsG.get(data, "altitude"); // NOI18N
    2.84 -        }
    2.85 +        public abstract Double getAltitude();
    2.86          
    2.87          /**  The altitude accuracy is specified in meters. 
    2.88           * If the implementation cannot provide altitude information, 
    2.89 @@ -130,19 +127,23 @@
    2.90           * must be a non-negative real number.
    2.91           * @return value in meters; may return null, if the information is not available 
    2.92           */
    2.93 -        public Double getAltitudeAccuracy() {
    2.94 -            return (Double)JsG.get(data, "altitudeAccuracy"); // NOI18N
    2.95 -        }
    2.96 +        public abstract Double getAltitudeAccuracy();
    2.97          
    2.98 -        /** @return may return null, if the information is not available */
    2.99 -        public Double getHeading() {
   2.100 -            return (Double)JsG.get(data, "heading"); // NOI18N
   2.101 -        }
   2.102 +        /** Denotes the direction of travel of the device and 
   2.103 +         * is specified in degrees 
   2.104 +         * counting clockwise relative to the true north. 
   2.105 +         * 
   2.106 +         * @return value from 0 to 360 - may return <code>null</code>, 
   2.107 +         *   if the information is not available 
   2.108 +         */
   2.109 +        public abstract Double getHeading();
   2.110          
   2.111 -        /** @return may return null, if the information is not available */
   2.112 -        public Double getSpeed() {
   2.113 -            return (Double)JsG.get(data, "speed"); // NOI18N
   2.114 -        }
   2.115 +        /** Denotes the magnitude of the horizontal component of the 
   2.116 +         * device's current velocity and is specified in meters per second.
   2.117 +         * 
   2.118 +         * @return may return null, if the information is not available 
   2.119 +         */
   2.120 +        public abstract Double getSpeed();
   2.121      } // end of Coordinates
   2.122  
   2.123      /** Rather than subclassing this class directly consider using {@link OnLocation}
   2.124 @@ -155,7 +156,7 @@
   2.125          private boolean enableHighAccuracy;
   2.126          private long timeout;
   2.127          private long maximumAge;
   2.128 -        volatile JsH handle;
   2.129 +        volatile JsH<?> handle;
   2.130  
   2.131          /** Creates new instance of this handle.
   2.132           * 
   2.133 @@ -184,7 +185,12 @@
   2.134           * @return true, if one can call {@link #start}.
   2.135           */
   2.136          public final boolean isSupported() {
   2.137 -            return JsG.hasGeolocation();
   2.138 +            JsH<?> p = seekProviders(null, null);
   2.139 +            if (p != null) {
   2.140 +                p.stop();
   2.141 +                return true;
   2.142 +            }
   2.143 +            return false;
   2.144          }
   2.145  
   2.146          /** Turns on high accuracy mode as specified by the 
   2.147 @@ -224,38 +230,106 @@
   2.148              if (handle != null) {
   2.149                  return;
   2.150              }
   2.151 -            handle = new JsH();
   2.152 +            
   2.153 +            Exception[] problem = { null };
   2.154 +            StringBuilder sb = new StringBuilder();
   2.155 +            sb.append("[");
   2.156 +            JsH<?> h = seekProviders(sb, problem);
   2.157 +            sb.append("\n]");
   2.158              try {
   2.159 -                if (!isSupported()) {
   2.160 -                    throw new IllegalStateException("geolocation API not supported");
   2.161 +                if (problem[0] != null) {
   2.162 +                    onError(problem[0]);
   2.163 +                    return;
   2.164                  }
   2.165 -                handle.start();
   2.166 -            } catch (Exception ex) {
   2.167 +                if (h == null) {
   2.168 +                    onError(new IllegalStateException("geolocation API not supported. Among providers: " + sb));
   2.169 +                }
   2.170 +                synchronized (this) {
   2.171 +                    if (handle != null) {
   2.172 +                        onError(new IllegalStateException("Parallel request"));
   2.173 +                    }
   2.174 +                    handle = h;
   2.175 +                }
   2.176 +            } catch (Throwable thr) {
   2.177 +                LOG.log(Level.INFO, "Problems delivering onError report", thr);
   2.178 +            }
   2.179 +        }
   2.180 +
   2.181 +        private JsH<?> seekProviders(StringBuilder sb, Exception[] problem) {
   2.182 +            BrwsrCtx ctx = BrwsrCtx.findDefault(getClass());
   2.183 +            JsH<?> h = seekProviders(Contexts.find(ctx, GLProvider.class), null, sb, problem);
   2.184 +            if (h == null) {
   2.185 +                h = seekProviders(null, ServiceLoader.load(GLProvider.class), sb, problem);
   2.186 +            }
   2.187 +            if (h == null) {
   2.188 +                h = seekProviders(new JsGLProvider(), null, sb, problem);
   2.189 +            }
   2.190 +            return h;
   2.191 +        }
   2.192 +
   2.193 +        private JsH<?> seekProviders(
   2.194 +            GLProvider single, Iterable<GLProvider> set,
   2.195 +            StringBuilder sb, Exception[] problem
   2.196 +        ) {
   2.197 +            if (set == null) {
   2.198 +                if (single == null) {
   2.199 +                    return null;
   2.200 +                }
   2.201 +                set = Collections.singleton(single);
   2.202 +            }
   2.203 +            JsH<?> h = null;
   2.204 +            for (GLProvider<?,?> p : set) {
   2.205 +                if (sb != null) {
   2.206 +                    if (sb.length() > 1) {
   2.207 +                        sb.append(',');
   2.208 +                    }
   2.209 +                    sb.append("\n  ").append(p.getClass().getName());
   2.210 +                }
   2.211                  try {
   2.212 -                    onError(ex);
   2.213 -                } catch (Throwable thr) {
   2.214 -                    LOG.log(Level.INFO, "Problems delivering onError report", thr);
   2.215 +                    h = createHandle(p);
   2.216 +                } catch (Exception ex) {
   2.217 +                    LOG.log(Level.INFO, "Problems when starting " + p.getClass().getName(), ex);
   2.218 +                    if (problem != null && problem[0] == null) {
   2.219 +                        problem[0] = ex;
   2.220 +                    }
   2.221 +                }
   2.222 +                if (h != null) {
   2.223 +                    break;
   2.224                  }
   2.225              }
   2.226 +            return h;
   2.227          }
   2.228  
   2.229          /** Stops all pending requests. After this call no further callbacks
   2.230           * can be obtained. Does nothing if no query or watch was in progress.
   2.231           */
   2.232          public final void stop() {
   2.233 -            JsH h = handle;
   2.234 -            if (h == null) {
   2.235 -                return;
   2.236 +            JsH h;
   2.237 +            synchronized (this) {
   2.238 +                h = handle;
   2.239 +                if (h == null) {
   2.240 +                    return;
   2.241 +                }
   2.242 +                handle = null;
   2.243              }
   2.244 -            handle = null;
   2.245              h.stop();
   2.246          }
   2.247 +        
   2.248 +        private <Watch> JsH<Watch> createHandle(GLProvider<?,Watch> p) {
   2.249 +            JsH<Watch> temp = new JsH<Watch>(p);
   2.250 +            return temp.watch == null ? null : temp;
   2.251 +        }
   2.252  
   2.253 -        private final class JsH extends JsG {
   2.254 -            long watch;
   2.255 +        private final class JsH<Watch> extends GLProvider<?, Watch>.Callback {
   2.256 +            private final Watch watch;
   2.257 +            
   2.258 +            public JsH(GLProvider<?, Watch> p) {
   2.259 +                p.super();
   2.260 +                this.watch = start(oneTime, enableHighAccuracy, timeout, maximumAge);
   2.261 +            }
   2.262              
   2.263              @Override
   2.264 -            public void onLocation(Object position) {
   2.265 +            public void onLocation(Position position) {
   2.266                  if (handle != this) {
   2.267                      return;
   2.268                  }
   2.269 @@ -263,39 +337,29 @@
   2.270                      stop();
   2.271                  }
   2.272                  try {
   2.273 -                    Handle.this.onLocation(new Position(position));
   2.274 +                    Handle.this.onLocation(position);
   2.275                  } catch (Throwable ex) {
   2.276                      LOG.log(Level.SEVERE, null, ex);
   2.277                  }
   2.278              }
   2.279  
   2.280              @Override
   2.281 -            public void onError(final String message, int code) {
   2.282 +            public void onError(Exception err) {
   2.283                  if (handle != this) {
   2.284                      return;
   2.285                  }
   2.286                  if (oneTime) {
   2.287 -                    stop();
   2.288 +                    stop(watch);
   2.289                  }
   2.290                  try {
   2.291 -                    final Exception err = new Exception(message + " errno: " + code) {
   2.292 -                        @Override
   2.293 -                        public String getLocalizedMessage() {
   2.294 -                            return message;
   2.295 -                        }
   2.296 -                    };
   2.297                      Handle.this.onError(err);
   2.298                  } catch (Throwable ex) {
   2.299                      LOG.log(Level.SEVERE, null, ex);
   2.300                  }
   2.301              }
   2.302  
   2.303 -            final void start() {
   2.304 -                watch = start(oneTime, enableHighAccuracy, timeout, maximumAge);
   2.305 -            }
   2.306 -
   2.307              protected final void stop() {
   2.308 -                super.stop(watch);
   2.309 +                stop(watch);
   2.310              }
   2.311          }
   2.312      }
     3.1 --- a/geo/src/main/java/org/netbeans/html/geo/impl/JsG.java	Tue Aug 26 18:38:36 2014 +0200
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,107 +0,0 @@
     3.4 -/**
     3.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3.6 - *
     3.7 - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     3.8 - *
     3.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    3.10 - * Other names may be trademarks of their respective owners.
    3.11 - *
    3.12 - * The contents of this file are subject to the terms of either the GNU
    3.13 - * General Public License Version 2 only ("GPL") or the Common
    3.14 - * Development and Distribution License("CDDL") (collectively, the
    3.15 - * "License"). You may not use this file except in compliance with the
    3.16 - * License. You can obtain a copy of the License at
    3.17 - * http://www.netbeans.org/cddl-gplv2.html
    3.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    3.19 - * specific language governing permissions and limitations under the
    3.20 - * License.  When distributing the software, include this License Header
    3.21 - * Notice in each file and include the License file at
    3.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    3.23 - * particular file as subject to the "Classpath" exception as provided
    3.24 - * by Oracle in the GPL Version 2 section of the License file that
    3.25 - * accompanied this code. If applicable, add the following below the
    3.26 - * License Header, with the fields enclosed by brackets [] replaced by
    3.27 - * your own identifying information:
    3.28 - * "Portions Copyrighted [year] [name of copyright owner]"
    3.29 - *
    3.30 - * Contributor(s):
    3.31 - *
    3.32 - * The Original Software is NetBeans. The Initial Developer of the Original
    3.33 - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    3.34 - *
    3.35 - * If you wish your version of this file to be governed by only the CDDL
    3.36 - * or only the GPL Version 2, indicate your decision by adding
    3.37 - * "[Contributor] elects to include this software in this distribution
    3.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
    3.39 - * single choice of license, a recipient has the option to distribute
    3.40 - * your version of this file under either the CDDL, the GPL Version 2 or
    3.41 - * to extend the choice of license to its licensees as provided above.
    3.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
    3.43 - * Version 2 license, then the option applies only if the new code is
    3.44 - * made subject to such option by the copyright holder.
    3.45 - */
    3.46 -package org.netbeans.html.geo.impl;
    3.47 -
    3.48 -import net.java.html.js.JavaScriptBody;
    3.49 -
    3.50 -/** Implementation class to deal with browser's <code>navigator.geolocation</code> 
    3.51 - * object.
    3.52 - *
    3.53 - * @author Jaroslav Tulach
    3.54 - */
    3.55 -public abstract class JsG {
    3.56 -    protected JsG() {
    3.57 -        if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
    3.58 -            throw new IllegalStateException();
    3.59 -        }
    3.60 -    }
    3.61 -    
    3.62 -    public abstract void onLocation(Object position);
    3.63 -    public abstract void onError(String message, int code);
    3.64 -    
    3.65 -    @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
    3.66 -    public static boolean hasGeolocation() {
    3.67 -        return false;
    3.68 -    }
    3.69 -
    3.70 -    @JavaScriptBody(
    3.71 -        args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, 
    3.72 -        javacall = true, 
    3.73 -        body = 
    3.74 -        "var self = this;\n" +
    3.75 -        "var ok = function (position) {\n" +
    3.76 -        "  self.@org.netbeans.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
    3.77 -        "};\n" +
    3.78 -        "var fail = function (error) {\n" +
    3.79 -        "  self.@org.netbeans.html.geo.impl.JsG::onError(Ljava/lang/String;I)(error.message, error.code);\n" +
    3.80 -        "};\n" +
    3.81 -        "var options = {};\n" +
    3.82 -        "options.enableHighAccuracy = enableHighAccuracy;\n" +
    3.83 -        "if (timeout >= 0) options.timeout = timeout;\n" +
    3.84 -        "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
    3.85 -        "if (onlyOnce) {\n" +
    3.86 -        "  navigator.geolocation.getCurrentPosition(ok, fail, options);\n" +
    3.87 -        "  return 0;\n" +
    3.88 -        "} else {\n" +
    3.89 -        "  return navigator.geolocation.watchPosition(ok, fail, options);\n" +
    3.90 -        "}\n"
    3.91 -    )
    3.92 -    protected long start(
    3.93 -        boolean onlyOnce, 
    3.94 -        boolean enableHighAccuracy,
    3.95 -        long timeout,
    3.96 -        long maximumAge
    3.97 -    ) {
    3.98 -        return -1;
    3.99 -    }
   3.100 -    
   3.101 -    @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
   3.102 -    protected void stop(long watch) {
   3.103 -    }
   3.104 -
   3.105 -    @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
   3.106 -    public static Object get(Object self, String property) {
   3.107 -        return null;
   3.108 -    }
   3.109 -
   3.110 -}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/JsGLProvider.java	Wed Aug 27 18:45:51 2014 +0200
     4.3 @@ -0,0 +1,154 @@
     4.4 +/**
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     4.8 + *
     4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    4.10 + * Other names may be trademarks of their respective owners.
    4.11 + *
    4.12 + * The contents of this file are subject to the terms of either the GNU
    4.13 + * General Public License Version 2 only ("GPL") or the Common
    4.14 + * Development and Distribution License("CDDL") (collectively, the
    4.15 + * "License"). You may not use this file except in compliance with the
    4.16 + * License. You can obtain a copy of the License at
    4.17 + * http://www.netbeans.org/cddl-gplv2.html
    4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    4.19 + * specific language governing permissions and limitations under the
    4.20 + * License.  When distributing the software, include this License Header
    4.21 + * Notice in each file and include the License file at
    4.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    4.23 + * particular file as subject to the "Classpath" exception as provided
    4.24 + * by Oracle in the GPL Version 2 section of the License file that
    4.25 + * accompanied this code. If applicable, add the following below the
    4.26 + * License Header, with the fields enclosed by brackets [] replaced by
    4.27 + * your own identifying information:
    4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    4.29 + *
    4.30 + * Contributor(s):
    4.31 + *
    4.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    4.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    4.34 + *
    4.35 + * If you wish your version of this file to be governed by only the CDDL
    4.36 + * or only the GPL Version 2, indicate your decision by adding
    4.37 + * "[Contributor] elects to include this software in this distribution
    4.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    4.39 + * single choice of license, a recipient has the option to distribute
    4.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    4.41 + * to extend the choice of license to its licensees as provided above.
    4.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    4.43 + * Version 2 license, then the option applies only if the new code is
    4.44 + * made subject to such option by the copyright holder.
    4.45 + */
    4.46 +package org.netbeans.html.geo.impl;
    4.47 +
    4.48 +import net.java.html.js.JavaScriptBody;
    4.49 +import org.netbeans.html.geo.spi.GLProvider;
    4.50 +
    4.51 +/** Implementation class to deal with browser's <code>navigator.geolocation</code> 
    4.52 + * object.
    4.53 + *
    4.54 + * @author Jaroslav Tulach
    4.55 + */
    4.56 +public final class JsGLProvider extends GLProvider<Object, Long> {
    4.57 +    public JsGLProvider() {
    4.58 +    }
    4.59 +    
    4.60 +    @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
    4.61 +    private static boolean hasGeolocation() {
    4.62 +        return false;
    4.63 +    }
    4.64 +
    4.65 +    @JavaScriptBody(
    4.66 +        args = { "c", "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, 
    4.67 +        javacall = true, 
    4.68 +        body = 
    4.69 +        "var self = this;\n" +
    4.70 +        "var ok = function (position) {\n" +
    4.71 +        "  self.@org.netbeans.html.geo.impl.JsGLProvider::onLocation(Ljava/lang/Object;Ljava/lang/Object;)(c, position);\n" +
    4.72 +        "};\n" +
    4.73 +        "var fail = function (error) {\n" +
    4.74 +        "  self.@org.netbeans.html.geo.impl.JsGLProvider::onError(Ljava/lang/Object;Ljava/lang/String;I)(c, error.message, error.code);\n" +
    4.75 +        "};\n" +
    4.76 +        "var options = {};\n" +
    4.77 +        "options.enableHighAccuracy = enableHighAccuracy;\n" +
    4.78 +        "if (timeout >= 0) options.timeout = timeout;\n" +
    4.79 +        "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
    4.80 +        "if (onlyOnce) {\n" +
    4.81 +        "  navigator.geolocation.getCurrentPosition(ok, fail, options);\n" +
    4.82 +        "  return 0;\n" +
    4.83 +        "} else {\n" +
    4.84 +        "  return navigator.geolocation.watchPosition(ok, fail, options);\n" +
    4.85 +        "}\n"
    4.86 +    )
    4.87 +    private long doStart(
    4.88 +        Callback c,
    4.89 +        boolean onlyOnce, 
    4.90 +        boolean enableHighAccuracy,
    4.91 +        long timeout,
    4.92 +        long maximumAge
    4.93 +    ) {
    4.94 +        return -1;
    4.95 +    }
    4.96 +    
    4.97 +    protected void stop(long watch) {
    4.98 +    }
    4.99 +
   4.100 +    @Override
   4.101 +    public Long start(Callback c, boolean oneTime, boolean enableHighAccuracy, long timeout, long maximumAge) {
   4.102 +        if (!hasGeolocation()) {
   4.103 +            return null;
   4.104 +        }
   4.105 +        return doStart(c, oneTime, enableHighAccuracy, timeout, maximumAge);
   4.106 +    }
   4.107 +    
   4.108 +    final void onLocation(Object c, Object p) {
   4.109 +        callback((Callback)c, timeStamp(p), p, null);
   4.110 +    }
   4.111 +    
   4.112 +    final void onError(Object c, final String msg, int code) {
   4.113 +        final Exception err = new Exception(msg + " errno: " + code) {
   4.114 +            @Override
   4.115 +            public String getLocalizedMessage() {
   4.116 +                return msg;
   4.117 +            }
   4.118 +        };
   4.119 +        callback((Callback)c, 0L, null, err);
   4.120 +    }
   4.121 +
   4.122 +    @Override
   4.123 +    @JavaScriptBody(args = {"watch"}, body = "navigator.geolocation.clearWatch(watch);")
   4.124 +    public native void stop(Long watch);
   4.125 +
   4.126 +    @JavaScriptBody(args = { "p" }, body = "return p.timestamp;")
   4.127 +    private static native long timeStamp(Object position);
   4.128 +
   4.129 +    @Override
   4.130 +    @JavaScriptBody(args = { "coords" }, body = "return coords.coords.latitude;")
   4.131 +    protected native double latitude(Object coords);
   4.132 +
   4.133 +    @Override
   4.134 +    @JavaScriptBody(args = { "coords" }, body = "return coords.coords.longitude;")
   4.135 +    protected native double longitude(Object coords);
   4.136 +
   4.137 +    @Override
   4.138 +    @JavaScriptBody(args = { "coords" }, body = "return coords.coords.accuracy;")
   4.139 +    protected native double accuracy(Object coords);
   4.140 +
   4.141 +    @Override
   4.142 +    @JavaScriptBody(args = {"coords"}, body = "return coords.coords.altitude ? coords.coords.altitude : null;")
   4.143 +    protected native Double altitude(Object coords);
   4.144 +
   4.145 +    @Override
   4.146 +    @JavaScriptBody(args = {"coords"}, body = "return coords.coords.altitudeAccuracy ? coords.coords.altitudeAccuracy : null;")
   4.147 +    protected native Double altitudeAccuracy(Object coords);
   4.148 +
   4.149 +    @Override
   4.150 +    @JavaScriptBody(args = {"coords"}, body = "return coords.coords.heading ? coords.coords.heading : null;")
   4.151 +    protected native Double heading(Object coords);
   4.152 +
   4.153 +    @Override
   4.154 +    @JavaScriptBody(args = {"coords"}, body = "return coords.coords.speed ? coords.coords.speed : null;")
   4.155 +    protected native Double speed(Object coords);
   4.156 +
   4.157 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/geo/src/main/java/org/netbeans/html/geo/spi/CoordImpl.java	Wed Aug 27 18:45:51 2014 +0200
     5.3 @@ -0,0 +1,87 @@
     5.4 +/**
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5.8 + *
     5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    5.10 + * Other names may be trademarks of their respective owners.
    5.11 + *
    5.12 + * The contents of this file are subject to the terms of either the GNU
    5.13 + * General Public License Version 2 only ("GPL") or the Common
    5.14 + * Development and Distribution License("CDDL") (collectively, the
    5.15 + * "License"). You may not use this file except in compliance with the
    5.16 + * License. You can obtain a copy of the License at
    5.17 + * http://www.netbeans.org/cddl-gplv2.html
    5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    5.19 + * specific language governing permissions and limitations under the
    5.20 + * License.  When distributing the software, include this License Header
    5.21 + * Notice in each file and include the License file at
    5.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    5.23 + * particular file as subject to the "Classpath" exception as provided
    5.24 + * by Oracle in the GPL Version 2 section of the License file that
    5.25 + * accompanied this code. If applicable, add the following below the
    5.26 + * License Header, with the fields enclosed by brackets [] replaced by
    5.27 + * your own identifying information:
    5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    5.29 + *
    5.30 + * Contributor(s):
    5.31 + *
    5.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    5.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    5.34 + *
    5.35 + * If you wish your version of this file to be governed by only the CDDL
    5.36 + * or only the GPL Version 2, indicate your decision by adding
    5.37 + * "[Contributor] elects to include this software in this distribution
    5.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    5.39 + * single choice of license, a recipient has the option to distribute
    5.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    5.41 + * to extend the choice of license to its licensees as provided above.
    5.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    5.43 + * Version 2 license, then the option applies only if the new code is
    5.44 + * made subject to such option by the copyright holder.
    5.45 + */
    5.46 +package org.netbeans.html.geo.spi;
    5.47 +
    5.48 +import net.java.html.geo.Position;
    5.49 +
    5.50 +/**
    5.51 + *
    5.52 + * @author Jaroslav Tulach
    5.53 + */
    5.54 +final class CoordImpl<Coords> extends Position.Coordinates {
    5.55 +    private final Coords data;
    5.56 +    private final GLProvider<Coords, ?> provider;
    5.57 +
    5.58 +    CoordImpl(Coords data, GLProvider<Coords, ?> p) {
    5.59 +        this.data = data;
    5.60 +        this.provider = p;
    5.61 +    }
    5.62 +
    5.63 +    @Override public double getLatitude() {
    5.64 +        return provider.latitude(data);
    5.65 +    }
    5.66 +
    5.67 +    @Override public double getLongitude() {
    5.68 +        return provider.longitude(data);
    5.69 +    }
    5.70 +
    5.71 +    @Override public double getAccuracy() {
    5.72 +        return provider.accuracy(data);
    5.73 +    }
    5.74 +
    5.75 +    @Override public Double getAltitude() {
    5.76 +        return provider.altitude(data);
    5.77 +    }
    5.78 +
    5.79 +    @Override public Double getAltitudeAccuracy() {
    5.80 +        return provider.altitudeAccuracy(data);
    5.81 +    }
    5.82 +
    5.83 +    @Override public Double getHeading() {
    5.84 +        return provider.heading(data);
    5.85 +    }
    5.86 +
    5.87 +    @Override public Double getSpeed() {
    5.88 +        return provider.speed(data);
    5.89 +    }
    5.90 +} // end of CoordImpl
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java	Wed Aug 27 18:45:51 2014 +0200
     6.3 @@ -0,0 +1,270 @@
     6.4 +/**
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     6.8 + *
     6.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    6.10 + * Other names may be trademarks of their respective owners.
    6.11 + *
    6.12 + * The contents of this file are subject to the terms of either the GNU
    6.13 + * General Public License Version 2 only ("GPL") or the Common
    6.14 + * Development and Distribution License("CDDL") (collectively, the
    6.15 + * "License"). You may not use this file except in compliance with the
    6.16 + * License. You can obtain a copy of the License at
    6.17 + * http://www.netbeans.org/cddl-gplv2.html
    6.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    6.19 + * specific language governing permissions and limitations under the
    6.20 + * License.  When distributing the software, include this License Header
    6.21 + * Notice in each file and include the License file at
    6.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    6.23 + * particular file as subject to the "Classpath" exception as provided
    6.24 + * by Oracle in the GPL Version 2 section of the License file that
    6.25 + * accompanied this code. If applicable, add the following below the
    6.26 + * License Header, with the fields enclosed by brackets [] replaced by
    6.27 + * your own identifying information:
    6.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    6.29 + *
    6.30 + * Contributor(s):
    6.31 + *
    6.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    6.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    6.34 + *
    6.35 + * If you wish your version of this file to be governed by only the CDDL
    6.36 + * or only the GPL Version 2, indicate your decision by adding
    6.37 + * "[Contributor] elects to include this software in this distribution
    6.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    6.39 + * single choice of license, a recipient has the option to distribute
    6.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    6.41 + * to extend the choice of license to its licensees as provided above.
    6.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    6.43 + * Version 2 license, then the option applies only if the new code is
    6.44 + * made subject to such option by the copyright holder.
    6.45 + */
    6.46 +
    6.47 +package org.netbeans.html.geo.spi;
    6.48 +
    6.49 +import net.java.html.BrwsrCtx;
    6.50 +import net.java.html.geo.Position;
    6.51 +import net.java.html.geo.Position.Handle;
    6.52 +import net.java.html.geo.Position.Coordinates;
    6.53 +import org.netbeans.html.context.spi.Contexts;
    6.54 +import org.openide.util.lookup.ServiceProvider;
    6.55 +
    6.56 +/** SPI for those who wish to provide their own way of obtaining geolocation.
    6.57 + * Subclass this class, implement its method and register it into the system.
    6.58 + * You can either use {@link ServiceProvider} to register globally, or 
    6.59 + * one can register into {@link BrwsrCtx} (via 
    6.60 + * {@link Contexts.Builder#register(java.lang.Class, java.lang.Object, int) context builder}).
    6.61 + * <p>
    6.62 + * There is default system provider (used as a fallback) based on 
    6.63 + * <a href="http://www.w3.org/TR/geolocation-API/">
    6.64 + * W3C's Geolocation</a> specification - if you are running inside a
    6.65 + * browser that supports such standard and you are satisfied with its
    6.66 + * behavior, you don't have to register anything.
    6.67 + * <p>
    6.68 + * The provider serves two purposes: 
    6.69 + * <ol>
    6.70 + *   <li>
    6.71 + *     It handles a geolocation request and creates a "watch" to represent it -
    6.72 + *     to do so implement the {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) start} 
    6.73 + *     method and the {@link #stop(java.lang.Object) stop} method.
    6.74 + *   </li>
    6.75 + *   <li>
    6.76 + *     Once the location is found, the provider needs to 
    6.77 + *     {@link #callback(org.netbeans.html.geo.spi.GLProvider.Callback, long, java.lang.Object, java.lang.Exception) call back}
    6.78 + *     with appropriate location information which can be extracted
    6.79 + *     later via {@link #latitude(java.lang.Object)} {@link #longitude(java.lang.Object)}, and
    6.80 + *     other methods in this that also need to be implemented.
    6.81 + *   </li>
    6.82 + * </ol>
    6.83 + * <p>
    6.84 + * The provider is based on a 
    6.85 + * <a href="http://wiki.apidesign.org/wiki/Singletonizer" target="_blank">singletonizer</a> 
    6.86 + * pattern (applied twice)
    6.87 + * and as such one is only required to subclass just the {@link GLProvider} 
    6.88 + * and otherwise has freedom choosing what classes to use
    6.89 + * to represent coordinates and watches. For example if it is enough to use
    6.90 + * an array for coordinates and a long number for a watch, one can do:
    6.91 + * <pre>
    6.92 + * <b>public final class</b> MyGeoProvider extends {@link GLProvider}&lt;Double[], Long&gt; {
    6.93 + *   <em>// somehow implement the methods</em>
    6.94 + * }
    6.95 + * </pre>
    6.96 + *
    6.97 + * @author Jaroslav Tulach
    6.98 + * @param <Watch> your choosen type to represent one query (one time) or watch (repeated) request -
    6.99 + *   this type is used in {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) start}
   6.100 + *   and {@link #stop(java.lang.Object) stop} methods.
   6.101 + * 
   6.102 + * @param <Coords> your choosen type to represent geolocation coordinates -
   6.103 + *   use in many methods in this class like {@link #latitude(java.lang.Object)} and
   6.104 + *   {@link #longitude(java.lang.Object)}.
   6.105 + * 
   6.106 + * @since 1.0
   6.107 + */
   6.108 +public abstract class GLProvider<Coords,Watch> {
   6.109 +    /** Start obtaining geolocation.
   6.110 +     * When the client {@link Handle#start() requests location} (and
   6.111 +     * your provider is found) this method should initialize the request or 
   6.112 +     * return <code>null</code> to give chance to another provider.
   6.113 +     * 
   6.114 +     * @param c the callback to {@link #callback(org.netbeans.html.geo.spi.GLProvider.Callback, long, java.lang.Object, java.lang.Exception) use when location is found} -
   6.115 +     *    keep it, you'll need it later
   6.116 +     * @param oneTime one time request vs. repeated requests
   6.117 +     *    - mimics value provided in {@link Handle#Handle(boolean) constructor}
   6.118 +     * @param enableHighAccuracy mimics value of
   6.119 +     *    {@link Handle#setHighAccuracy(boolean)}
   6.120 +     * @param timeout mimics value of
   6.121 +     *    {@link Handle#setTimeout(long)}
   6.122 +     * @param maximumAge mimics value of 
   6.123 +     *    {@link Handle#setMaximumAge(long)}
   6.124 +     * 
   6.125 +     * @return an object representing the request (so it can be {@link #stop(java.lang.Object) stopped} later)
   6.126 +     *   or <code>null</code> if this provider was unable to start the request
   6.127 +     */
   6.128 +    protected abstract Watch start(
   6.129 +        Callback c, 
   6.130 +        boolean oneTime, boolean enableHighAccuracy, 
   6.131 +        long timeout, long maximumAge
   6.132 +    );
   6.133 +    
   6.134 +    /** Called when a geolocation request should be stopped.
   6.135 +     * 
   6.136 +     * @param watch the watch returned when {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) starting}
   6.137 +     *   the request
   6.138 +     */
   6.139 +    protected abstract void stop(Watch watch);
   6.140 +
   6.141 +    /** Invoke this method when your provider obtained request location.
   6.142 +     * This single method is used for notification of success (when <code>ex</code>
   6.143 +     * argument is <code>null</code> and <code>position</code> is provided) or 
   6.144 +     * a failure (when <code>ex</code> argument is non-<code>null</code>).
   6.145 +     * A successful requests leads in call to {@link Handle#onLocation(net.java.html.geo.Position)}
   6.146 +     * while an error report leads to call to {@link Handle#onError(java.lang.Exception)}.
   6.147 +     * 
   6.148 +     * @param c the callback as provided when {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) starting}
   6.149 +     *   the request
   6.150 +     * @param timestamp milliseconds since epoch when the location has been obtained
   6.151 +     * @param position your own, internal, representation of geolocation
   6.152 +     *   coordinates - will be passed back to other methods of this class
   6.153 +     *   like {@link #latitude(java.lang.Object)} and {@link #longitude(java.lang.Object)}.
   6.154 +     *   Can be <code>null</code> if <code>ex</code> is non-<code>null</code>
   6.155 +     * @param ex an exception to signal an error - should be <code>null</code>
   6.156 +     *   when one notifies the successfully obtained <code>position</code>
   6.157 +     */
   6.158 +    protected final void callback(
   6.159 +        Callback c,
   6.160 +        long timestamp, Coords position,
   6.161 +        Exception ex
   6.162 +    ) {
   6.163 +        if (ex == null) {
   6.164 +            c.onLocation(new Position(timestamp, new CoordImpl<Coords>(position, this)));
   6.165 +        } else {
   6.166 +            c.onError(ex);
   6.167 +        }
   6.168 +    }
   6.169 +
   6.170 +    /** Extracts value for {@link Coordinates#getLatitude()}.
   6.171 +     * @param coords your own internal representation of coordinates.
   6.172 +     * @return geographic coordinate specified in decimal degrees.
   6.173 +     */
   6.174 +    protected abstract double latitude(Coords coords);
   6.175 +    
   6.176 +    /** Extracts value for {@link Coordinates#getLatitude()}.
   6.177 +     * @param coords your own internal representation of coordinates.
   6.178 +     * @return geographic coordinate specified in decimal degrees.
   6.179 +     */
   6.180 +    protected abstract double longitude(Coords coords);
   6.181 +    
   6.182 +    /** Extracts value for {@link Coordinates#getLatitude()}.
   6.183 +     * The accuracy attribute denotes the accuracy level of the latitude 
   6.184 +     * and longitude coordinates.
   6.185 +     * 
   6.186 +     * @param coords your own internal representation of coordinates.
   6.187 +     * @return accuracy in meters
   6.188 +     */
   6.189 +    protected abstract double accuracy(Coords coords);
   6.190 +    
   6.191 +    /** Extracts value for {@link Coordinates#getAltitude()}.
   6.192 +     * Denotes the height of the position, specified in meters above the ellipsoid.
   6.193 +     * 
   6.194 +     * @param coords your own internal representation of coordinates.
   6.195 +     * @return value in meters, may return null, if the information is not available
   6.196 +     */
   6.197 +    protected abstract Double altitude(Coords coords);
   6.198 +    
   6.199 +    /** Extracts value for {@link Coordinates#getAltitudeAccuracy()} -
   6.200 +     * the altitude accuracy is specified in meters. 
   6.201 +     * 
   6.202 +     * @param coords your own internal representation of coordinates.
   6.203 +     * @return value in meters; may return null, if the information is not available
   6.204 +     */
   6.205 +    protected abstract Double altitudeAccuracy(Coords coords);
   6.206 +    
   6.207 +    /** Extracts value for {@link Coordinates#getHeading()}.
   6.208 +     * Denotes the magnitude of the horizontal component of the 
   6.209 +     * device's current velocity and is specified in meters per second.
   6.210 +     * 
   6.211 +     * @param coords your own internal representation of coordinates.
   6.212 +     * @return may return null, if the information is not available 
   6.213 +     */
   6.214 +    protected abstract Double heading(Coords coords);
   6.215 +    
   6.216 +    /** Extracts value for {@link Coordinates#getSpeed()}.
   6.217 +     * Denotes the magnitude of the horizontal component of the 
   6.218 +     * device's current velocity and is specified in meters per second.
   6.219 +     * 
   6.220 +     * @param coords your own internal representation of coordinates.
   6.221 +     * @return may return null, if the information is not available
   6.222 +     */
   6.223 +    protected abstract Double speed(Coords coords);
   6.224 +    
   6.225 +    /** A callback interface used by {@link GLProvider} to notify back
   6.226 +     * results of its findings.
   6.227 +     */
   6.228 +    public abstract class Callback {
   6.229 +        /** Restricted constructor.
   6.230 +         * @throws IllegalStateException most of the time
   6.231 +         */
   6.232 +        protected Callback() {
   6.233 +            if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
   6.234 +                throw new IllegalStateException();
   6.235 +            }
   6.236 +        }
   6.237 +
   6.238 +        /** Initiates a geolocation request. 
   6.239 +         * 
   6.240 +         * @param oneTime one time request vs. repeated requests
   6.241 +         *    - mimics value provided in {@link Handle#Handle(boolean) constructor}
   6.242 +         * @param enableHighAccuracy mimics value of
   6.243 +         *    {@link Handle#setHighAccuracy(boolean)}
   6.244 +         * @param timeout mimics value of
   6.245 +         *    {@link Handle#setTimeout(long)}
   6.246 +         * @param maximumAge mimics value of 
   6.247 +         *    {@link Handle#setMaximumAge(long)}
   6.248 +         * @return an object representing the request (so it can be {@link #stop(java.lang.Object) stopped} later)
   6.249 +         *   or <code>null</code> if this provider was unable to start the request
   6.250 +         */
   6.251 +        protected final Watch start(boolean oneTime, boolean enableHighAccuracy, long timeout, long maximumAge) {
   6.252 +            return GLProvider.this.start(this, oneTime, enableHighAccuracy, timeout, maximumAge);
   6.253 +        }
   6.254 +  
   6.255 +        /** Stops the watch request.
   6.256 +         * @param w the watch
   6.257 +         */
   6.258 +        protected final void stop(Watch w) {
   6.259 +            GLProvider.this.stop(w);
   6.260 +        }
   6.261 +        
   6.262 +        /** Called when a position is successfully obtained.
   6.263 +         * 
   6.264 +         * @param p the position
   6.265 +         */
   6.266 +        protected abstract void onLocation(Position p);
   6.267 +        
   6.268 +        /** Called on an error during obtaining of the position.
   6.269 +         * @param ex exception describing the error
   6.270 +         */
   6.271 +        protected abstract void onError(Exception ex);
   6.272 +    }
   6.273 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/geo/src/main/java/org/netbeans/html/geo/spi/package.html	Wed Aug 27 18:45:51 2014 +0200
     7.3 @@ -0,0 +1,59 @@
     7.4 +<!--
     7.5 +
     7.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.7 +
     7.8 +    Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     7.9 +
    7.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    7.11 +    Other names may be trademarks of their respective owners.
    7.12 +
    7.13 +    The contents of this file are subject to the terms of either the GNU
    7.14 +    General Public License Version 2 only ("GPL") or the Common
    7.15 +    Development and Distribution License("CDDL") (collectively, the
    7.16 +    "License"). You may not use this file except in compliance with the
    7.17 +    License. You can obtain a copy of the License at
    7.18 +    http://www.netbeans.org/cddl-gplv2.html
    7.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    7.20 +    specific language governing permissions and limitations under the
    7.21 +    License.  When distributing the software, include this License Header
    7.22 +    Notice in each file and include the License file at
    7.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    7.24 +    particular file as subject to the "Classpath" exception as provided
    7.25 +    by Oracle in the GPL Version 2 section of the License file that
    7.26 +    accompanied this code. If applicable, add the following below the
    7.27 +    License Header, with the fields enclosed by brackets [] replaced by
    7.28 +    your own identifying information:
    7.29 +    "Portions Copyrighted [year] [name of copyright owner]"
    7.30 +
    7.31 +    Contributor(s):
    7.32 +
    7.33 +    The Original Software is NetBeans. The Initial Developer of the Original
    7.34 +    Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    7.35 +
    7.36 +    If you wish your version of this file to be governed by only the CDDL
    7.37 +    or only the GPL Version 2, indicate your decision by adding
    7.38 +    "[Contributor] elects to include this software in this distribution
    7.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
    7.40 +    single choice of license, a recipient has the option to distribute
    7.41 +    your version of this file under either the CDDL, the GPL Version 2 or
    7.42 +    to extend the choice of license to its licensees as provided above.
    7.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
    7.44 +    Version 2 license, then the option applies only if the new code is
    7.45 +    made subject to such option by the copyright holder.
    7.46 +
    7.47 +-->
    7.48 +<!DOCTYPE html>
    7.49 +<html>
    7.50 +    <head>
    7.51 +        <title>Geolocation SPI</title>
    7.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    7.53 +        <meta name="viewport" content="width=device-width">
    7.54 +    </head>
    7.55 +    <body>
    7.56 +        <div>
    7.57 +            Service provider interfaces for those willing to 
    7.58 +            {@link org.netbeans.html.geo.spi.GLProvider provide their own way}
    7.59 +            of obtaining proper geolocation.
    7.60 +        </div>
    7.61 +    </body>
    7.62 +</html>
     8.1 --- a/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Tue Aug 26 18:38:36 2014 +0200
     8.2 +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Wed Aug 27 18:45:51 2014 +0200
     8.3 @@ -66,7 +66,7 @@
     8.4      @Test public void onLocationHandleCallback() throws Throwable {
     8.5          net.java.html.geo.Position.Handle h = OnLocationHandle.createQuery();
     8.6          cnt = 0;
     8.7 -        h.onLocation(new Position(null));
     8.8 +        h.onLocation(new Position(0L, null));
     8.9          assertEquals(cnt, 1, "The callback has been made");
    8.10      }
    8.11  
    8.12 @@ -104,7 +104,7 @@
    8.13      @Test public void onInstanceCallback() throws Throwable {
    8.14          OnLocationTest t = new OnLocationTest();
    8.15          net.java.html.geo.Position.Handle h = InstanceHandle.createWatch(t);
    8.16 -        h.onLocation(new Position(null));
    8.17 +        h.onLocation(new Position(0L, null));
    8.18          assertEquals(t.instCnt, 1, "One callback made");
    8.19      }
    8.20  
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/geo/src/test/java/org/netbeans/html/geo/spi/CoordImplTest.java	Wed Aug 27 18:45:51 2014 +0200
     9.3 @@ -0,0 +1,111 @@
     9.4 +/**
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     9.8 + *
     9.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    9.10 + * Other names may be trademarks of their respective owners.
    9.11 + *
    9.12 + * The contents of this file are subject to the terms of either the GNU
    9.13 + * General Public License Version 2 only ("GPL") or the Common
    9.14 + * Development and Distribution License("CDDL") (collectively, the
    9.15 + * "License"). You may not use this file except in compliance with the
    9.16 + * License. You can obtain a copy of the License at
    9.17 + * http://www.netbeans.org/cddl-gplv2.html
    9.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.19 + * specific language governing permissions and limitations under the
    9.20 + * License.  When distributing the software, include this License Header
    9.21 + * Notice in each file and include the License file at
    9.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    9.23 + * particular file as subject to the "Classpath" exception as provided
    9.24 + * by Oracle in the GPL Version 2 section of the License file that
    9.25 + * accompanied this code. If applicable, add the following below the
    9.26 + * License Header, with the fields enclosed by brackets [] replaced by
    9.27 + * your own identifying information:
    9.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.29 + *
    9.30 + * Contributor(s):
    9.31 + *
    9.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    9.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    9.34 + *
    9.35 + * If you wish your version of this file to be governed by only the CDDL
    9.36 + * or only the GPL Version 2, indicate your decision by adding
    9.37 + * "[Contributor] elects to include this software in this distribution
    9.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.39 + * single choice of license, a recipient has the option to distribute
    9.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.41 + * to extend the choice of license to its licensees as provided above.
    9.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.43 + * Version 2 license, then the option applies only if the new code is
    9.44 + * made subject to such option by the copyright holder.
    9.45 + */
    9.46 +
    9.47 +package org.netbeans.html.geo.spi;
    9.48 +
    9.49 +import static org.testng.Assert.*;
    9.50 +import org.testng.annotations.AfterClass;
    9.51 +import org.testng.annotations.AfterMethod;
    9.52 +import org.testng.annotations.BeforeClass;
    9.53 +import org.testng.annotations.BeforeMethod;
    9.54 +import org.testng.annotations.Test;
    9.55 +
    9.56 +/**
    9.57 + *
    9.58 + * @author Jaroslav Tulach
    9.59 + */
    9.60 +public class CoordImplTest extends GLProvider<Double, Object> {
    9.61 +    
    9.62 +    public CoordImplTest() {
    9.63 +    }
    9.64 +    @Test public void testGetLatitude() {
    9.65 +        CoordImpl<Double> c = new CoordImpl<Double>(50.5, this);
    9.66 +        assertEquals(c.getLatitude(), 50.5, 0.1, "Latitude returned as provided");
    9.67 +    }
    9.68 +
    9.69 +    @Override
    9.70 +    protected Object start(Callback c, boolean oneTime, boolean enableHighAccuracy, long timeout, long maximumAge) {
    9.71 +        throw new UnsupportedOperationException();
    9.72 +    }
    9.73 +
    9.74 +    @Override
    9.75 +    protected void stop(Object watch) {
    9.76 +        throw new UnsupportedOperationException();
    9.77 +    }
    9.78 +
    9.79 +    @Override
    9.80 +    protected double latitude(Double coords) {
    9.81 +        return coords;
    9.82 +    }
    9.83 +
    9.84 +    @Override
    9.85 +    protected double longitude(Double coords) {
    9.86 +        throw new UnsupportedOperationException();
    9.87 +    }
    9.88 +
    9.89 +    @Override
    9.90 +    protected double accuracy(Double coords) {
    9.91 +        throw new UnsupportedOperationException();
    9.92 +    }
    9.93 +
    9.94 +    @Override
    9.95 +    protected Double altitude(Double coords) {
    9.96 +        throw new UnsupportedOperationException();
    9.97 +    }
    9.98 +
    9.99 +    @Override
   9.100 +    protected Double altitudeAccuracy(Double coords) {
   9.101 +        throw new UnsupportedOperationException();
   9.102 +    }
   9.103 +
   9.104 +    @Override
   9.105 +    protected Double heading(Double coords) {
   9.106 +        throw new UnsupportedOperationException();
   9.107 +    }
   9.108 +
   9.109 +    @Override
   9.110 +    protected Double speed(Double coords) {
   9.111 +        throw new UnsupportedOperationException();
   9.112 +    }
   9.113 +    
   9.114 +}