summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/gecko/permissions/PermissionBlock.java
blob: a4d72f2584eeec818b390097a71aaf4a1ca3ab14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.permissions;

import org.mozilla.gecko.util.ThreadUtils;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;

/**
 * Helper class to run code blocks depending on whether a user has granted or denied certain runtime permissions.
 */
public class PermissionBlock {
    private final PermissionsHelper helper;

    private Context context;
    private String[] permissions;
    private boolean onUIThread;
    private Runnable onPermissionsGranted;
    private Runnable onPermissionsDenied;
    private boolean doNotPrompt;

    /* package-private */ PermissionBlock(Context context, PermissionsHelper helper) {
        this.context = context;
        this.helper = helper;
    }

    /**
     * Determine whether the app has been granted the specified permissions.
     */
    public PermissionBlock withPermissions(@NonNull String... permissions) {
        this.permissions = permissions;
        return this;
    }

    /**
     * Execute all callbacks on the UI thread.
     */
    public PermissionBlock onUIThread() {
        this.onUIThread = true;
        return this;
    }

    /**
     * Do not prompt the user to accept the permission if it has not been granted yet.
     */
    public PermissionBlock doNotPrompt() {
        doNotPrompt = true;
        return this;
    }

    /**
     * If the condition is true then do not prompt the user to accept the permission if it has not
     * been granted yet.
     */
    public PermissionBlock doNotPromptIf(boolean condition) {
        if (condition) {
            doNotPrompt();
        }

        return this;
    }

    /**
     * Execute this permission block. Calling this method will prompt the user if needed.
     */
    public void run() {
        run(null);
    }

    /**
     * Execute the specified runnable if the app has been granted all permissions. Calling this method will prompt the
     * user if needed.
     */
    public void run(Runnable onPermissionsGranted) {
        if (!doNotPrompt && !(context instanceof Activity)) {
            throw new IllegalStateException("You need to either specify doNotPrompt() or pass in an Activity context");
        }

        this.onPermissionsGranted = onPermissionsGranted;

        if (hasPermissions(context)) {
            onPermissionsGranted();
        } else if (doNotPrompt) {
            onPermissionsDenied();
        } else {
            Permissions.prompt((Activity) context, this);
        }

        // This reference is no longer needed. Let's clear it now to avoid memory leaks.
        context = null;
    }

    /**
     * Execute this fallback if at least one permission has not been granted.
     */
    public PermissionBlock andFallback(@NonNull Runnable onPermissionsDenied) {
        this.onPermissionsDenied = onPermissionsDenied;
        return this;
    }

    /* package-private */ void onPermissionsGranted() {
        executeRunnable(onPermissionsGranted);
    }

    /* package-private */ void onPermissionsDenied() {
        executeRunnable(onPermissionsDenied);
    }

    private void executeRunnable(Runnable runnable) {
        if (runnable == null) {
            return;
        }

        if (onUIThread) {
            ThreadUtils.postToUiThread(runnable);
        } else {
            runnable.run();
        }
    }

    /* package-private */ String[] getPermissions() {
        return permissions;
    }

    /* packacge-private */ boolean hasPermissions(Context context) {
        return helper.hasPermissions(context, permissions);
    }
}