Skip to content
This repository was archived by the owner on Apr 3, 2020. It is now read-only.

Commit 709a387

Browse files
michaelbaiCommit bot
michaelbai
authored and
Commit bot
committed
Cherry-pick: Deny the geolocation permission request by default.
This patch denies the request if there is no response when GeolocationPermission.Callback object is gc-ed. TBR=boliu BUG=513752 NOTRY=true NOPRESUBMIT=true Review URL: https://codereview.chromium.org/1267103003 Cr-Commit-Position: refs/heads/master@{#341760} (cherry picked from commit 97d22bb) Review URL: https://codereview.chromium.org/1277563002 Cr-Commit-Position: refs/branch-heads/2454@{#235} Cr-Branched-From: 12bfc33-refs/heads/master@{#338390}
1 parent d1d9bbc commit 709a387

File tree

4 files changed

+144
-47
lines changed

4 files changed

+144
-47
lines changed

android_webview/java/src/org/chromium/android_webview/AwContents.java

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
import android.view.animation.AnimationUtils;
3838
import android.view.inputmethod.EditorInfo;
3939
import android.view.inputmethod.InputConnection;
40-
import android.webkit.GeolocationPermissions;
4140
import android.webkit.JavascriptInterface;
4241
import android.webkit.ValueCallback;
4342
import android.widget.OverScroller;
4443

44+
import org.chromium.android_webview.permission.AwGeolocationCallback;
4545
import org.chromium.android_webview.permission.AwPermissionRequest;
4646
import org.chromium.base.CalledByNative;
4747
import org.chromium.base.JNINamespace;
@@ -2410,25 +2410,13 @@ private void onReceivedHttpAuthRequest(AwHttpAuthHandler handler, String host, S
24102410
mContentsClient.onReceivedHttpAuthRequest(handler, host, realm);
24112411
}
24122412

2413-
private class AwGeolocationCallback implements GeolocationPermissions.Callback {
2413+
public AwGeolocationPermissions getGeolocationPermissions() {
2414+
return mBrowserContext.getGeolocationPermissions();
2415+
}
24142416

2415-
@Override
2416-
public void invoke(final String origin, final boolean allow, final boolean retain) {
2417-
ThreadUtils.runOnUiThread(new Runnable() {
2418-
@Override
2419-
public void run() {
2420-
if (retain) {
2421-
if (allow) {
2422-
mBrowserContext.getGeolocationPermissions().allow(origin);
2423-
} else {
2424-
mBrowserContext.getGeolocationPermissions().deny(origin);
2425-
}
2426-
}
2427-
if (isDestroyed()) return;
2428-
nativeInvokeGeolocationCallback(mNativeAwContents, allow, origin);
2429-
}
2430-
});
2431-
}
2417+
public void invokeGeolocationCallback(boolean value, String requestingFrame) {
2418+
if (isDestroyed()) return;
2419+
nativeInvokeGeolocationCallback(mNativeAwContents, value, requestingFrame);
24322420
}
24332421

24342422
@CalledByNative
@@ -2447,7 +2435,7 @@ private void onGeolocationPermissionsShowPrompt(String origin) {
24472435
return;
24482436
}
24492437
mContentsClient.onGeolocationPermissionsShowPrompt(
2450-
origin, new AwGeolocationCallback());
2438+
origin, new AwGeolocationCallback(origin, this));
24512439
}
24522440

24532441
@CalledByNative
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2015 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package org.chromium.android_webview.permission;
6+
7+
import android.webkit.GeolocationPermissions;
8+
9+
import org.chromium.android_webview.AwContents;
10+
import org.chromium.base.Log;
11+
import org.chromium.base.ThreadUtils;
12+
import org.chromium.content.common.CleanupReference;
13+
14+
import java.lang.ref.WeakReference;
15+
16+
/**
17+
* This class implements GeolocationPermissions.Callback, and will be sent to
18+
* WebView applications through WebChromeClient.onGeolocationPermissionsShowPrompt().
19+
*/
20+
public class AwGeolocationCallback implements GeolocationPermissions.Callback {
21+
private static final String TAG = "cr.Geolocation";
22+
23+
private CleanupRunable mCleanupRunable;
24+
private CleanupReference mCleanupReference;
25+
26+
private static class CleanupRunable implements Runnable {
27+
private WeakReference<AwContents> mAwContents;
28+
private boolean mAllow;
29+
private boolean mRetain;
30+
private String mOrigin;
31+
32+
public CleanupRunable(AwContents awContents, String origin) {
33+
mAwContents = new WeakReference<AwContents>(awContents);
34+
mOrigin = origin;
35+
}
36+
37+
@Override
38+
public void run() {
39+
assert ThreadUtils.runningOnUiThread();
40+
AwContents awContents = mAwContents.get();
41+
if (awContents == null) return;
42+
if (mRetain) {
43+
if (mAllow) {
44+
awContents.getGeolocationPermissions().allow(mOrigin);
45+
} else {
46+
awContents.getGeolocationPermissions().deny(mOrigin);
47+
}
48+
}
49+
awContents.invokeGeolocationCallback(mAllow, mOrigin);
50+
}
51+
52+
public void setResponse(String origin, boolean allow, boolean retain) {
53+
mOrigin = origin;
54+
mAllow = allow;
55+
mRetain = retain;
56+
}
57+
}
58+
59+
public AwGeolocationCallback(String origin, AwContents awContents) {
60+
mCleanupRunable = new CleanupRunable(awContents, origin);
61+
mCleanupReference = new CleanupReference(this, mCleanupRunable);
62+
}
63+
64+
@Override
65+
public void invoke(String origin, boolean allow, boolean retain) {
66+
if (mCleanupRunable == null || mCleanupReference == null) {
67+
Log.w(TAG, "Response for this geolocation request has been received."
68+
+ " Ignoring subsequent responses");
69+
return;
70+
}
71+
mCleanupRunable.setResponse(origin, allow, retain);
72+
mCleanupReference.cleanupNow();
73+
mCleanupReference = null;
74+
mCleanupRunable = null;
75+
}
76+
}

android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66

77
import android.os.Build;
88
import android.test.suitebuilder.annotation.MediumTest;
9+
import android.test.suitebuilder.annotation.SmallTest;
910
import android.webkit.GeolocationPermissions;
1011

1112
import org.chromium.android_webview.AwContents;
13+
import org.chromium.base.annotations.SuppressFBWarnings;
1214
import org.chromium.base.test.util.Feature;
1315
import org.chromium.base.test.util.MinAndroidSdkLevel;
1416
import org.chromium.content.browser.LocationProviderFactory;
@@ -37,52 +39,65 @@ public class GeolocationTest extends AwTestBase {
3739
+ " function gotPos(position) {\n"
3840
+ " positionCount++;\n"
3941
+ " }\n"
42+
+ " function errorCallback(error){"
43+
+ " window.document.title = 'deny';"
44+
+ " console.log('navigator.getCurrentPosition error: ', error);"
45+
+ " }"
4046
+ " function initiate_getCurrentPosition() {\n"
4147
+ " navigator.geolocation.getCurrentPosition(\n"
42-
+ " gotPos, function() { }, { });\n"
48+
+ " gotPos, errorCallback, { });\n"
4349
+ " }\n"
4450
+ " function initiate_watchPosition() {\n"
4551
+ " navigator.geolocation.watchPosition(\n"
46-
+ " gotPos, function() { }, { });\n"
52+
+ " gotPos, errorCallback, { });\n"
4753
+ " }\n"
4854
+ " </script>\n"
4955
+ " </head>\n"
5056
+ " <body>\n"
5157
+ " </body>\n"
5258
+ "</html>";
5359

54-
@Override
55-
public void setUp() throws Exception {
56-
super.setUp();
57-
mContentsClient = new TestAwContentsClient() {
58-
@Override
59-
public void onGeolocationPermissionsShowPrompt(String origin,
60-
GeolocationPermissions.Callback callback) {
61-
callback.invoke(origin, true, true);
62-
}
63-
};
64-
mAwContents = createAwTestContainerViewOnMainSync(mContentsClient).getAwContents();
65-
enableJavaScriptOnUiThread(mAwContents);
66-
setupGeolocation();
60+
private static class GrantPermisionAwContentClient extends TestAwContentsClient {
61+
@Override
62+
public void onGeolocationPermissionsShowPrompt(String origin,
63+
GeolocationPermissions.Callback callback) {
64+
callback.invoke(origin, true, true);
65+
}
6766
}
6867

69-
@Override
70-
public void tearDown() throws Exception {
71-
mMockLocationProvider.stopUpdates();
72-
super.tearDown();
68+
private static class DefaultPermisionAwContentClient extends TestAwContentsClient {
69+
@Override
70+
public void onGeolocationPermissionsShowPrompt(String origin,
71+
GeolocationPermissions.Callback callback) {
72+
// This method is empty intentionally to simulate callback is not referenced.
73+
}
7374
}
7475

75-
private void setupGeolocation() {
76+
private void initAwContents(TestAwContentsClient contentsClient) throws Exception {
77+
mContentsClient = contentsClient;
78+
mAwContents = createAwTestContainerViewOnMainSync(mContentsClient).getAwContents();
79+
enableJavaScriptOnUiThread(mAwContents);
7680
getInstrumentation().runOnMainSync(new Runnable() {
7781
@Override
7882
public void run() {
7983
mAwContents.getSettings().setGeolocationEnabled(true);
8084
}
8185
});
86+
}
87+
88+
@Override
89+
public void setUp() throws Exception {
90+
super.setUp();
8291
mMockLocationProvider = new MockLocationProvider();
8392
LocationProviderFactory.setLocationProviderImpl(mMockLocationProvider);
8493
}
8594

95+
@Override
96+
public void tearDown() throws Exception {
97+
mMockLocationProvider.stopUpdates();
98+
super.tearDown();
99+
}
100+
86101
private int getPositionCountFromJS() {
87102
int result = -1;
88103
try {
@@ -110,6 +125,7 @@ public Boolean call() throws Exception {
110125
@MediumTest
111126
@Feature({"AndroidWebView"})
112127
public void testGetPosition() throws Throwable {
128+
initAwContents(new GrantPermisionAwContentClient());
113129
loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
114130
RAW_HTML, "text/html", false);
115131

@@ -137,6 +153,7 @@ public Boolean call() throws Exception {
137153
@MediumTest
138154
@Feature({"AndroidWebView"})
139155
public void testWatchPosition() throws Throwable {
156+
initAwContents(new GrantPermisionAwContentClient());
140157
loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
141158
RAW_HTML, "text/html", false);
142159

@@ -153,6 +170,7 @@ public Boolean call() throws Exception {
153170
@MediumTest
154171
@Feature({"AndroidWebView"})
155172
public void testPauseGeolocationOnPause() throws Throwable {
173+
initAwContents(new GrantPermisionAwContentClient());
156174
// Start a watch going.
157175
loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
158176
RAW_HTML, "text/html", false);
@@ -204,6 +222,7 @@ public Boolean call() throws Exception {
204222
@MediumTest
205223
@Feature({"AndroidWebView"})
206224
public void testPauseAwContentsBeforeNavigating() throws Throwable {
225+
initAwContents(new GrantPermisionAwContentClient());
207226
getInstrumentation().runOnMainSync(new Runnable() {
208227
@Override
209228
public void run() {
@@ -241,6 +260,7 @@ public Boolean call() throws Exception {
241260
@MediumTest
242261
@Feature({"AndroidWebView"})
243262
public void testResumeWhenNotStarted() throws Throwable {
263+
initAwContents(new GrantPermisionAwContentClient());
244264
getInstrumentation().runOnMainSync(new Runnable() {
245265
@Override
246266
public void run() {
@@ -261,4 +281,23 @@ public void run() {
261281
ensureGeolocationRunning(false);
262282
}
263283

284+
@Feature({"AndroidWebView"})
285+
@SmallTest
286+
public void testDenyAccessByDefault() throws Throwable {
287+
initAwContents(new DefaultPermisionAwContentClient());
288+
loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
289+
RAW_HTML, "text/html", false);
290+
291+
mAwContents.evaluateJavaScriptForTests("initiate_getCurrentPosition();", null);
292+
293+
poll(new Callable<Boolean>() {
294+
@SuppressFBWarnings("DM_GC")
295+
@Override
296+
public Boolean call() throws Exception {
297+
Runtime.getRuntime().gc();
298+
return "deny".equals(getTitleOnUiThread(mAwContents));
299+
}
300+
});
301+
}
302+
264303
}

android_webview/native/aw_contents.cc

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,8 @@ void AwContents::InvokeGeolocationCallback(JNIEnv* env,
491491
jboolean value,
492492
jstring origin) {
493493
DCHECK_CURRENTLY_ON(BrowserThread::UI);
494-
if (pending_geolocation_prompts_.empty()) {
495-
LOG(WARNING) << "Response for this geolocation request has been received."
496-
<< " Ignoring subsequent responses";
494+
if (pending_geolocation_prompts_.empty())
497495
return;
498-
}
499496

500497
GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin));
501498
if (callback_origin.GetOrigin() ==
@@ -506,9 +503,6 @@ void AwContents::InvokeGeolocationCallback(JNIEnv* env,
506503
ShowGeolocationPromptHelper(java_ref_,
507504
pending_geolocation_prompts_.front().first);
508505
}
509-
} else {
510-
LOG(WARNING) << "Response for this geolocation request has been received."
511-
<< " Ignoring subsequent responses";
512506
}
513507
}
514508

0 commit comments

Comments
 (0)