mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 1369107 - 2. Ask for app location permission from JS; r=esawin
For location permission, we first show a prompt for the website, then on higher Android versions, we show a prompt for the app. For the app prompt, right now we show that from GeckoView code in GeckoAppShell. However, if we move the app prompt into ContentPermissionPrompt.js alongside the website prompt, we can then remove the code in GeckoAppShell and eliminate this app permission dependency from GeckoView code. MozReview-Commit-ID: GSCqClPROwn
This commit is contained in:
parent
5674b33e77
commit
7eab0ee43f
@ -7,8 +7,9 @@ const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/RuntimePermissions.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const kEntities = {
|
||||
"contacts": "contacts",
|
||||
@ -31,20 +32,20 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request, type, denyUnknown) {
|
||||
handleExistingPermission: function handleExistingPermission(request, type, denyUnknown, callback) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
callback(/* allow */ true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
request.cancel();
|
||||
callback(/* allow */ false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (denyUnknown && result == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
|
||||
request.cancel();
|
||||
callback(/* allow */ false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -79,19 +80,37 @@ ContentPermissionPrompt.prototype = {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
let callback = (allow) => {
|
||||
if (!allow) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
if (perm.type === "geolocation") {
|
||||
RuntimePermissions.waitForPermissions(
|
||||
RuntimePermissions.ACCESS_FINE_LOCATION).then((granted) => {
|
||||
(granted ? request.allow : request.cancel)();
|
||||
});
|
||||
return;
|
||||
}
|
||||
request.allow();
|
||||
};
|
||||
|
||||
// Returns true if the request was handled
|
||||
let access = (perm.access && perm.access !== "unused") ?
|
||||
(perm.type + "-" + perm.access) : perm.type;
|
||||
if (this.handleExistingPermission(request, access,
|
||||
/* denyUnknown */ isApp || PROMPT_FOR_UNKNOWN.indexOf(perm.type) < 0))
|
||||
/* denyUnknown */ isApp || PROMPT_FOR_UNKNOWN.indexOf(perm.type) < 0, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let chromeWin = this.getChromeForRequest(request);
|
||||
let tab = chromeWin.BrowserApp.getTabForWindow(request.window.top);
|
||||
if (!tab)
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
let entityName = kEntities[perm.type];
|
||||
@ -103,7 +122,7 @@ ContentPermissionPrompt.prototype = {
|
||||
if (aChecked || entityName == "desktopNotification2")
|
||||
Services.perms.addFromPrincipal(request.principal, access, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
|
||||
request.cancel();
|
||||
callback(/* allow */ false);
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -117,7 +136,7 @@ ContentPermissionPrompt.prototype = {
|
||||
Services.perms.addFromPrincipal(request.principal, access, Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||
}
|
||||
|
||||
request.allow();
|
||||
callback(/* allow */ true);
|
||||
},
|
||||
positive: true
|
||||
}];
|
||||
|
@ -285,7 +285,8 @@ public class GeckoAppShell
|
||||
return (location.hasAccuracy() && radius > 0) ? radius : 1001;
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission") // Permissions are explicitly checked for in enableLocation()
|
||||
// Permissions are explicitly checked when requesting content permission.
|
||||
@SuppressLint("MissingPermission")
|
||||
private static Location getLastKnownLocation(LocationManager lm) {
|
||||
Location lastKnownLocation = null;
|
||||
List<String> providers = lm.getAllProviders();
|
||||
@ -313,55 +314,58 @@ public class GeckoAppShell
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
@SuppressLint("MissingPermission") // Permissions are explicitly checked for within this method
|
||||
private static void enableLocation(final boolean enable) {
|
||||
final Runnable requestLocation = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LocationManager lm = getLocationManager(getApplicationContext());
|
||||
if (lm == null) {
|
||||
return;
|
||||
// Permissions are explicitly checked when requesting content permission.
|
||||
@SuppressLint("MissingPermission")
|
||||
/* package */ static void enableLocation(final boolean enable) {
|
||||
if (!ThreadUtils.isOnUiThread()) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
enableLocation(enable);
|
||||
} catch (final SecurityException e) {
|
||||
Log.e(LOGTAG, "No location permission", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enable) {
|
||||
lm.removeUpdates(getLocationListener());
|
||||
return;
|
||||
}
|
||||
LocationManager lm = getLocationManager(getApplicationContext());
|
||||
if (lm == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location lastKnownLocation = getLastKnownLocation(lm);
|
||||
if (lastKnownLocation != null) {
|
||||
getLocationListener().onLocationChanged(lastKnownLocation);
|
||||
}
|
||||
if (!enable) {
|
||||
lm.removeUpdates(getLocationListener());
|
||||
return;
|
||||
}
|
||||
|
||||
Criteria criteria = new Criteria();
|
||||
criteria.setSpeedRequired(false);
|
||||
criteria.setBearingRequired(false);
|
||||
criteria.setAltitudeRequired(false);
|
||||
if (locationHighAccuracyEnabled) {
|
||||
criteria.setAccuracy(Criteria.ACCURACY_FINE);
|
||||
criteria.setCostAllowed(true);
|
||||
criteria.setPowerRequirement(Criteria.POWER_HIGH);
|
||||
} else {
|
||||
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
|
||||
criteria.setCostAllowed(false);
|
||||
criteria.setPowerRequirement(Criteria.POWER_LOW);
|
||||
}
|
||||
Location lastKnownLocation = getLastKnownLocation(lm);
|
||||
if (lastKnownLocation != null) {
|
||||
getLocationListener().onLocationChanged(lastKnownLocation);
|
||||
}
|
||||
|
||||
String provider = lm.getBestProvider(criteria, true);
|
||||
if (provider == null)
|
||||
return;
|
||||
Criteria criteria = new Criteria();
|
||||
criteria.setSpeedRequired(false);
|
||||
criteria.setBearingRequired(false);
|
||||
criteria.setAltitudeRequired(false);
|
||||
if (locationHighAccuracyEnabled) {
|
||||
criteria.setAccuracy(Criteria.ACCURACY_FINE);
|
||||
criteria.setCostAllowed(true);
|
||||
criteria.setPowerRequirement(Criteria.POWER_HIGH);
|
||||
} else {
|
||||
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
|
||||
criteria.setCostAllowed(false);
|
||||
criteria.setPowerRequirement(Criteria.POWER_LOW);
|
||||
}
|
||||
|
||||
Looper l = Looper.getMainLooper();
|
||||
lm.requestLocationUpdates(provider, 100, 0.5f, getLocationListener(), l);
|
||||
}
|
||||
};
|
||||
String provider = lm.getBestProvider(criteria, true);
|
||||
if (provider == null)
|
||||
return;
|
||||
|
||||
Permissions
|
||||
.from((Activity) getContext())
|
||||
.withPermissions(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
.onUIThread()
|
||||
.doNotPromptIf(!enable)
|
||||
.run(requestLocation);
|
||||
Looper l = Looper.getMainLooper();
|
||||
lm.requestLocationUpdates(provider, 100, 0.5f, getLocationListener(), l);
|
||||
}
|
||||
|
||||
private static LocationManager getLocationManager(Context context) {
|
||||
|
@ -11,11 +11,13 @@ this.EXPORTED_SYMBOLS = ["RuntimePermissions"];
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// See: http://developer.android.com/reference/android/Manifest.permission.html
|
||||
const ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
|
||||
const CAMERA = "android.permission.CAMERA";
|
||||
const WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
|
||||
const RECORD_AUDIO = "android.permission.RECORD_AUDIO";
|
||||
const WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
|
||||
|
||||
var RuntimePermissions = {
|
||||
ACCESS_FINE_LOCATION: ACCESS_FINE_LOCATION,
|
||||
CAMERA: CAMERA,
|
||||
RECORD_AUDIO: RECORD_AUDIO,
|
||||
WRITE_EXTERNAL_STORAGE: WRITE_EXTERNAL_STORAGE,
|
||||
|
Loading…
Reference in New Issue
Block a user