Skip to content

Commit a2d5cb4

Browse files
committed
geolocation hacking
1 parent 9a03f9c commit a2d5cb4

6 files changed

Lines changed: 251 additions & 266 deletions

File tree

src/main/java/org/htmlunit/WebClientOptions.java

Lines changed: 121 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ public class WebClientOptions implements Serializable {
5858
private String[] sslClientProtocols_;
5959
private String[] sslClientCipherSuites_;
6060

61-
private boolean geolocationEnabled_;
6261
private boolean doNotTrackEnabled_;
6362
private String homePage_ = "https://www.htmlunit.org/";
6463
private ProxyConfig proxyConfig_;
@@ -75,6 +74,9 @@ public class WebClientOptions implements Serializable {
7574
private int screenWidth_ = DEFAULT_SCRREN_WIDTH;
7675
private int screenHeight_ = DEFAULT_SCRREN_HEIGHT;
7776

77+
private boolean geolocationEnabled_;
78+
private Geolocation geolocation_;
79+
7880
private boolean webSocketEnabled_ = true;
7981
private int webSocketMaxTextMessageSize_ = -1;
8082
private int webSocketMaxTextMessageBufferSize_ = -1;
@@ -412,24 +414,6 @@ public boolean isPopupBlockerEnabled() {
412414
return popupBlockerEnabled_;
413415
}
414416

415-
/**
416-
* Enables/disables Geolocation support. By default, this property is disabled.
417-
*
418-
* @param enabled {@code true} to enable Geolocation support
419-
*/
420-
public void setGeolocationEnabled(final boolean enabled) {
421-
geolocationEnabled_ = enabled;
422-
}
423-
424-
/**
425-
* Returns {@code true} if Geolocation is enabled.
426-
*
427-
* @return {@code true} if Geolocation is enabled
428-
*/
429-
public boolean isGeolocationEnabled() {
430-
return geolocationEnabled_;
431-
}
432-
433417
/**
434418
* Enables/disables "Do Not Track" support. By default, this property is disabled.
435419
*
@@ -879,4 +863,122 @@ public void setFetchPolyfillEnabled(final boolean enabled) {
879863
public boolean isFetchPolyfillEnabled() {
880864
return isFetchPolyfillEnabled_;
881865
}
866+
867+
/**
868+
* Enables/disables Geolocation support. By default, this property is disabled.
869+
*
870+
* @param enabled {@code true} to enable Geolocation support
871+
*/
872+
public void setGeolocationEnabled(final boolean enabled) {
873+
geolocationEnabled_ = enabled;
874+
}
875+
876+
/**
877+
* @return {@code true} if Geolocation is enabled
878+
*/
879+
public boolean isGeolocationEnabled() {
880+
return geolocationEnabled_;
881+
}
882+
883+
/**
884+
* @return the {@link Geolocation}
885+
*/
886+
public Geolocation getGeolocation() {
887+
return geolocation_;
888+
}
889+
890+
/**
891+
* Sets the {@link Geolocation} to be used.
892+
* @param geolocation the new location or null
893+
*/
894+
public void setGeolocation(final Geolocation geolocation) {
895+
geolocation_ = geolocation;
896+
}
897+
898+
public static class Geolocation {
899+
private final double accuracy_;
900+
private final double latitude_;
901+
private final double longitude_;
902+
private final Double altitude_;
903+
private final Double altitudeAccuracy_;
904+
private final Double heading_;
905+
private final Double speed_;
906+
907+
/**
908+
* Ctor.
909+
*
910+
* @param accuracy the accuracy
911+
* @param latitude the latitude
912+
* @param longitude the longitude
913+
* @param altitude the altitude or null
914+
* @param altitudeAccuracy the altitudeAccuracy or null
915+
* @param heading the heading or null
916+
* @param speed the speed or null
917+
*/
918+
public Geolocation(
919+
final double latitude,
920+
final double longitude,
921+
final double accuracy,
922+
final Double altitude,
923+
final Double altitudeAccuracy,
924+
final Double heading,
925+
final Double speed) {
926+
latitude_ = latitude;
927+
longitude_ = longitude;
928+
accuracy_ = accuracy;
929+
altitude_ = altitude;
930+
altitudeAccuracy_ = altitudeAccuracy;
931+
heading_ = heading;
932+
speed_ = speed;
933+
}
934+
935+
/**
936+
* @return the accuracy
937+
*/
938+
public double getAccuracy() {
939+
return accuracy_;
940+
}
941+
942+
/**
943+
* @return the latitude
944+
*/
945+
public double getLatitude() {
946+
return latitude_;
947+
}
948+
949+
/**
950+
* @return the longitude
951+
*/
952+
public double getLongitude() {
953+
return longitude_;
954+
}
955+
956+
/**
957+
* @return the longitude
958+
*/
959+
public Double getAltitude() {
960+
return altitude_;
961+
}
962+
963+
/**
964+
* @return the altitudeAccuracy
965+
*/
966+
public Double getAltitudeAccuracy() {
967+
return altitudeAccuracy_;
968+
}
969+
970+
/**
971+
* @return the heading
972+
*/
973+
public Double getHeading() {
974+
return heading_;
975+
}
976+
977+
/**
978+
* @return the speed
979+
*/
980+
public Double getSpeed() {
981+
return speed_;
982+
}
983+
}
882984
}

src/main/java/org/htmlunit/javascript/host/geo/Geolocation.java

Lines changed: 16 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,8 @@
1414
*/
1515
package org.htmlunit.javascript.host.geo;
1616

17-
import java.io.BufferedReader;
18-
import java.io.IOException;
19-
import java.io.InputStreamReader;
20-
import java.nio.charset.Charset;
21-
import java.util.ArrayList;
22-
import java.util.Iterator;
23-
import java.util.List;
24-
import java.util.Locale;
25-
26-
import org.apache.commons.lang3.StringUtils;
2717
import org.apache.commons.logging.Log;
2818
import org.apache.commons.logging.LogFactory;
29-
import org.htmlunit.BrowserVersion;
30-
import org.htmlunit.Page;
3119
import org.htmlunit.WebClient;
3220
import org.htmlunit.WebWindow;
3321
import org.htmlunit.corejs.javascript.Function;
@@ -51,9 +39,8 @@ public class Geolocation extends HtmlUnitScriptable {
5139

5240
private static final Log LOG = LogFactory.getLog(Geolocation.class);
5341

54-
/* Do not use this URL without Google permission! */
55-
private static String PROVIDER_URL_ = "https://maps.googleapis.com/maps/api/browserlocation/json";
5642
private Function successHandler_;
43+
private Function errorHandler_;
5744

5845
/**
5946
* Creates an instance.
@@ -62,10 +49,11 @@ public Geolocation() {
6249
}
6350

6451
/**
65-
* JavaScript constructor.
52+
* Creates an instance.
6653
*/
6754
@JsxConstructor
6855
public void jsConstructor() {
56+
throw JavaScriptEngine.reportRuntimeError("Illegal constructor.");
6957
}
7058

7159
/**
@@ -75,9 +63,10 @@ public void jsConstructor() {
7563
* @param options optional options
7664
*/
7765
@JsxFunction
78-
public void getCurrentPosition(final Function successCallback, final Object errorCallback,
66+
public void getCurrentPosition(final Function successCallback, final Function errorCallback,
7967
final Object options) {
8068
successHandler_ = successCallback;
69+
errorHandler_ = errorCallback;
8170

8271
final WebWindow webWindow = getWindow().getWebWindow();
8372
if (webWindow.getWebClient().getOptions().isGeolocationEnabled()) {
@@ -109,139 +98,20 @@ public void clearWatch(final int watchId) {
10998
}
11099

111100
void doGetPosition() {
112-
final String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
113-
String wifiStringString = null;
114-
if (os.contains("win")) {
115-
wifiStringString = getWifiStringWindows();
116-
}
117-
118-
if (wifiStringString == null) {
119-
if (LOG.isErrorEnabled()) {
120-
LOG.error("Operating System not supported: " + os);
121-
}
122-
}
123-
else {
124-
String url = PROVIDER_URL_;
125-
if (url.contains("?")) {
126-
url += '&';
127-
}
128-
else {
129-
url += '?';
130-
}
131-
url += "browser=firefox&sensor=true";
132-
url += wifiStringString;
133-
134-
while (url.length() >= 1900) {
135-
url = url.substring(0, url.lastIndexOf("&wifi="));
136-
}
137-
138-
if (LOG.isInfoEnabled()) {
139-
LOG.info("Invoking URL: " + url);
140-
}
141-
142-
try (WebClient webClient = new WebClient(BrowserVersion.FIREFOX)) {
143-
final Page page = webClient.getPage(url);
144-
final String content = page.getWebResponse().getContentAsString();
145-
if (LOG.isDebugEnabled()) {
146-
LOG.debug("Receieved Content: " + content);
147-
}
148-
final double latitude = Double.parseDouble(getJSONValue(content, "lat"));
149-
final double longitude = Double.parseDouble(getJSONValue(content, "lng"));
150-
final double accuracy = Double.parseDouble(getJSONValue(content, "accuracy"));
151-
152-
final GeolocationCoordinates coordinates = new GeolocationCoordinates(latitude, longitude, accuracy);
153-
coordinates.setPrototype(getPrototype(coordinates.getClass()));
154-
155-
final GeolocationPosition position = new GeolocationPosition(coordinates);
156-
position.setPrototype(getPrototype(position.getClass()));
101+
final WebWindow ww = getWindow().getWebWindow();
102+
final WebClient webClient = ww.getWebClient();
157103

158-
final WebWindow ww = getWindow().getWebWindow();
159-
final JavaScriptEngine jsEngine =
160-
(JavaScriptEngine) ww.getWebClient().getJavaScriptEngine();
161-
jsEngine.callFunction((HtmlPage) ww.getEnclosedPage(), successHandler_, this,
162-
getParentScope(), new Object[] {position});
163-
}
164-
catch (final Exception e) {
165-
LOG.error("", e);
166-
}
167-
}
168-
}
169-
170-
private static String getJSONValue(final String content, final String key) {
171-
final StringBuilder builder = new StringBuilder();
172-
int index = content.indexOf("\"" + key + "\"") + key.length() + 2;
173-
for (index = content.indexOf(':', index) + 1; index < content.length(); index++) {
174-
final char ch = content.charAt(index);
175-
if (ch == ',' || ch == '}') {
176-
break;
177-
}
178-
builder.append(ch);
179-
}
180-
return builder.toString().trim();
181-
}
104+
final org.htmlunit.WebClientOptions.Geolocation geolocation = webClient.getOptions().getGeolocation();
182105

183-
static String getWifiStringWindows() {
184-
final StringBuilder builder = new StringBuilder();
185-
try {
186-
final List<String> lines = runCommand("netsh wlan show networks mode=bssid");
187-
for (final Iterator<String> it = lines.iterator(); it.hasNext();) {
188-
String line = it.next();
189-
if (line.startsWith("SSID ")) {
190-
final String name = line.substring(line.lastIndexOf(' ') + 1);
191-
if (it.hasNext()) {
192-
it.next();
193-
}
194-
if (it.hasNext()) {
195-
it.next();
196-
}
197-
if (it.hasNext()) {
198-
it.next();
199-
}
200-
while (it.hasNext()) {
201-
line = it.next();
202-
if (line.trim().startsWith("BSSID ")) {
203-
final String mac = line.substring(line.lastIndexOf(' ') + 1);
204-
if (it.hasNext()) {
205-
line = it.next().trim();
206-
if (line.startsWith("Signal")) {
207-
final String signal = line.substring(line.lastIndexOf(' ') + 1, line.length() - 1);
208-
final int signalStrength = Integer.parseInt(signal) / 2 - 100;
209-
builder.append("&wifi=mac:")
210-
.append(mac.replace(':', '-'))
211-
.append("%7Cssid:")
212-
.append(name)
213-
.append("%7Css:")
214-
.append(signalStrength);
215-
}
216-
}
217-
}
218-
if (StringUtils.isBlank(line)) {
219-
break;
220-
}
221-
}
222-
}
223-
}
224-
}
225-
catch (final IOException e) {
226-
//
227-
}
228-
return builder.toString();
229-
}
106+
final GeolocationCoordinates coordinates = new GeolocationCoordinates(
107+
geolocation.getLatitude(), geolocation.getLongitude(), geolocation.getAccuracy());
108+
coordinates.setPrototype(getPrototype(coordinates.getClass()));
230109

231-
private static List<String> runCommand(final String command) throws IOException {
232-
final List<String> list = new ArrayList<>();
233-
final Process p = Runtime.getRuntime().exec(command);
234-
try (BufferedReader reader = new BufferedReader(
235-
new InputStreamReader(p.getInputStream(), Charset.defaultCharset()))) {
236-
String line;
237-
while ((line = reader.readLine()) != null) {
238-
list.add(line);
239-
}
240-
}
241-
return list;
242-
}
110+
final GeolocationPosition position = new GeolocationPosition(coordinates);
111+
position.setPrototype(getPrototype(position.getClass()));
243112

244-
static void setProviderUrl(final String url) {
245-
PROVIDER_URL_ = url;
113+
final JavaScriptEngine jsEngine = (JavaScriptEngine) ww.getWebClient().getJavaScriptEngine();
114+
jsEngine.callFunction((HtmlPage) ww.getEnclosedPage(), successHandler_, this,
115+
getParentScope(), new Object[] {position});
246116
}
247117
}

src/main/java/org/htmlunit/javascript/host/geo/GeolocationCoordinates.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
package org.htmlunit.javascript.host.geo;
1616

1717
import org.htmlunit.javascript.HtmlUnitScriptable;
18+
import org.htmlunit.javascript.JavaScriptEngine;
1819
import org.htmlunit.javascript.configuration.JsxClass;
20+
import org.htmlunit.javascript.configuration.JsxConstructor;
1921
import org.htmlunit.javascript.configuration.JsxGetter;
2022

2123
/**
@@ -43,6 +45,14 @@ public GeolocationCoordinates() {
4345
accuracy_ = accuracy;
4446
}
4547

48+
/**
49+
* Creates an instance.
50+
*/
51+
@JsxConstructor
52+
public void jsConstructor() {
53+
throw JavaScriptEngine.reportRuntimeError("Illegal constructor.");
54+
}
55+
4656
/**
4757
* Returns the latitude.
4858
* @return the latitude

0 commit comments

Comments
 (0)