summaryrefslogtreecommitdiffstats
path: root/mobile/android/docs/geckoview/consumer/permissions.rst
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/docs/geckoview/consumer/permissions.rst')
-rw-r--r--mobile/android/docs/geckoview/consumer/permissions.rst287
1 files changed, 287 insertions, 0 deletions
diff --git a/mobile/android/docs/geckoview/consumer/permissions.rst b/mobile/android/docs/geckoview/consumer/permissions.rst
new file mode 100644
index 0000000000..5dbab9b6b6
--- /dev/null
+++ b/mobile/android/docs/geckoview/consumer/permissions.rst
@@ -0,0 +1,287 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=============================
+Working with Site Permissions
+=============================
+
+When a website wants to access certain services on a user’s device, it
+will send out a permissions request. This document will explain how to
+use GeckoView to receive those requests, and respond to them by granting
+or denying those permissions.
+
+.. contents:: :local:
+
+The Permission Delegate
+-----------------------
+
+The way an app interacts with site permissions in GeckoView is through
+the
+`PermissionDelegate <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html>`_.
+There are three broad categories of permission that the
+``PermissionDelegate`` handles, Android Permissions, Content Permissions
+and Media Permissions. All site permissions handled by GeckoView fall
+into one of these three categories.
+
+To get notified about permission requests, you need to implement the
+``PermissionDelegate`` interface:
+
+.. code:: java
+
+ private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
+ @Override
+ public void onAndroidPermissionsRequest(final GeckoSession session,
+ final String[] permissions,
+ final Callback callback) { }
+
+ @Override
+ public void onContentPermissionRequest(final GeckoSession session,
+ final String uri,
+ final int type, final Callback callback) { }
+
+ @Override
+ public void onMediaPermissionRequest(final GeckoSession session,
+ final String uri,
+ final MediaSource[] video,
+ final MediaSource[] audio,
+ final MediaCallback callback) { }
+ }
+
+You will then need to register the delegate with your
+`GeckoSession <https://mozilla.github.io/geckoview/https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html>`_
+instance.
+
+.. code:: java
+
+ public class GeckoViewActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ...
+
+ final ExamplePermissionDelegate permission = new ExamplePermissionDelegate();
+ session.setPermissionDelegate(permission);
+
+ ...
+ }
+ }
+
+Android Permissions
+~~~~~~~~~~~~~~~~~~~
+
+Android permissions are requested whenever a site wants access to a
+device’s navigation or input capabilities.
+
+The user will often need to grant these Android permissions to the app
+alongside granting the Content or Media site permissions.
+
+When you receive an
+`onAndroidPermissionsRequest <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onAndroidPermissionsRequest(org.mozilla.geckoview.GeckoSession,java.lang.String[],org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback)>`_
+call, you will also receive the ``GeckoSession`` the request was sent
+from, an array containing the permissions that are being requested, and
+a
+`Callback`_
+to respond to the request. It is then up to the app to request those
+permissions from the device, which can be done using
+`requestPermissions <https://developer.android.com/reference/android/app/Activity#requestPermissions(java.lang.String%5B%5D,%2520int)>`_.
+
+Possible ``permissions`` values are:
+`ACCESS_COARSE_LOCATION <https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION>`_,
+`ACCESS_FINE_LOCATION <https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_FINE_LOCATION>`_,
+`CAMERA <https://developer.android.com/reference/android/Manifest.permission.html#CAMERA>`_
+or
+`RECORD_AUDIO <https://developer.android.com/reference/android/Manifest.permission.html#RECORD_AUDIO>`_.
+
+.. code:: java
+
+ private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
+ private Callback mCallback;
+
+ public void onRequestPermissionsResult(final String[] permissions,
+ final int[] grantResults) {
+ if (mCallback == null) { return; }
+
+ final Callback cb = mCallback;
+ mCallback = null;
+ for (final int result : grantResults) {
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ // At least one permission was not granted.
+ cb.reject();
+ return;
+ }
+ }
+ cb.grant();
+ }
+
+ @Override
+ public void onAndroidPermissionsRequest(final GeckoSession session,
+ final String[] permissions,
+ final Callback callback) {
+ mCallback = callback;
+ requestPermissions(permissions, androidPermissionRequestCode);
+ }
+ }
+
+ public class GeckoViewActivity extends AppCompatActivity {
+ @Override
+ public void onRequestPermissionsResult(final int requestCode,
+ final String[] permissions,
+ final int[] grantResults) {
+ if (requestCode == REQUEST_PERMISSIONS ||
+ requestCode == REQUEST_WRITE_EXTERNAL_STORAGE) {
+ final ExamplePermissionDelegate permission = (ExamplePermissionDelegate)
+ getCurrentSession().getPermissionDelegate();
+ permission.onRequestPermissionsResult(permissions, grantResults);
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+ }
+ }
+
+Content Permissions
+~~~~~~~~~~~~~~~~~~~
+
+Content permissions are requested whenever a site wants access to
+content that is stored on the device. The content permissions that can
+be requested through GeckoView are:
+`Geolocation <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_GEOLOCATION>`_,
+`Site Notifications <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_DESKTOP_NOTIFICATION>`_,
+`Persistent Storage <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_STORAGE>`_,
+`XR <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_XR>`_,
+`Autoplay Inaudible <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_AUTOPLAY_INAUDIBLE>`_,
+`Autoplay Audible <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_AUTOPLAY_AUDIBLE>`_,
+and
+`DRM Media access <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_MEDIA_KEY_SYSTEM_ACCESS>`_.
+Additionally, `tracking protection exceptions <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_TRACKING>`_
+are treated as a type of content permission.
+
+When you receive an
+`onContentPermissionRequest <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest(org.mozilla.geckoview.GeckoSession,org.mozilla.geckoview.GeckoSession.PermissionDelegate.ContentPermission)>`_
+call, you will also receive the ``GeckoSession`` the request was sent
+from, and all relevant information about the permission being requested
+stored in a `ContentPermission <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.ContentPermission.html>`_.
+It is then up to the app to present UI to the user asking for the
+permissions, and to notify GeckoView of the response via the returned
+``GeckoResult``.
+
+Once a permission has been set in this fashion, GeckoView will persist it
+across sessions until it is cleared or modified. When a page is loaded,
+the active permissions associated with it (both allowed and denied) will
+be reported in `onLocationChange <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.NavigationDelegate.html#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String,java.util.List)>`_
+as a list of ``ContentPermission`` objects; additionally, one may check all stored
+content permissions by calling `getAllPermissions <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/StorageController.html#getAllPermissions()>`_
+and the content permissions associated with a given URI by calling
+`getPermissions <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/StorageController.html#getPermissions(java.lang.String,java.lang.String)>`_.
+In order to modify an existing permission, you will need the associated
+``ContentPermission`` (which can be retrieved from any of the above methods);
+then, call `setPermission <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/StorageController.html#setPermission(org.mozilla.geckoview.GeckoSession.PermissionDelegate.ContentPermission,int)>`_
+with the desired new value, or `VALUE_PROMPT <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.ContentPermission.html#VALUE_PROMPT>`_
+if you wish to unset the permission and let the site request it again in the future.
+
+Media Permissions
+~~~~~~~~~~~~~~~~~
+
+Media permissions are requested whenever a site wants access to play or
+record media from the device’s camera and microphone.
+
+When you receive an
+`onMediaPermissionRequest <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest(org.mozilla.geckoview.GeckoSession,java.lang.String,org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource[],org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource[],org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback)>`_
+call, you will also receive the ``GeckoSession`` the request was sent
+from, the URI of the site that requested the permission, as a String,
+the list of video devices available, if requesting video, the list of
+audio devices available, if requesting audio, and a
+`MediaCallback <https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686>`_
+to respond to the request.
+
+It is up to the app to present UI to the user asking for the
+permissions, and to notify GeckoView of the response via the
+``MediaCallback``.
+
+*Please note, media permissions will still be requested if the
+associated device permissions have been denied if there are video or
+audio sources in that category that can still be accessed when listed.
+It is the responsibility of consumers to ensure that media permission
+requests are not displayed in this case.*
+
+.. code:: java
+
+ private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
+ @Override
+ public void onMediaPermissionRequest(final GeckoSession session,
+ final String uri,
+ final MediaSource[] video,
+ final MediaSource[] audio,
+ final MediaCallback callback) {
+ // Reject permission if Android permission has been previously denied.
+ if ((audio != null
+ && ContextCompat.checkSelfPermission(GeckoViewActivity.this,
+ Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
+ || (video != null
+ && ContextCompat.checkSelfPermission(GeckoViewActivity.this,
+ Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
+ callback.reject();
+ return;
+ }
+
+ final String host = Uri.parse(uri).getAuthority();
+ final String title;
+ if (audio == null) {
+ title = getString(R.string.request_video, host);
+ } else if (video == null) {
+ title = getString(R.string.request_audio, host);
+ } else {
+ title = getString(R.string.request_media, host);
+ }
+
+ // Get the media device name from the `MediaDevice`
+ String[] videoNames = normalizeMediaName(video);
+ String[] audioNames = normalizeMediaName(audio);
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+
+ // Create drop down boxes to allow users to select which device to grant permission to
+ final LinearLayout container = addStandardLayout(builder, title, null);
+ final Spinner videoSpinner;
+ if (video != null) {
+ videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames); // create spinner and add to alert UI
+ } else {
+ videoSpinner = null;
+ }
+
+ final Spinner audioSpinner;
+ if (audio != null) {
+ audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames); // create spinner and add to alert UI
+ } else {
+ audioSpinner = null;
+ }
+
+ builder.setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ // gather selected media devices and grant access
+ final MediaSource video = (videoSpinner != null)
+ ? (MediaSource) videoSpinner.getSelectedItem() : null;
+ final MediaSource audio = (audioSpinner != null)
+ ? (MediaSource) audioSpinner.getSelectedItem() : null;
+ callback.grant(video, audio);
+ }
+ });
+
+ final AlertDialog dialog = builder.create();
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(final DialogInterface dialog) {
+ callback.reject();
+ }
+ });
+ dialog.show();
+ }
+ }
+
+To see the ``PermissionsDelegate`` in action, you can find the full
+example implementation in the `GeckoView example
+app <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html>`_.
+
+.. _Callback: https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html