1// Copyright 2012 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
5package org.chromium.android_webview;
6
7import android.content.SharedPreferences;
8import android.webkit.ValueCallback;
9
10import org.chromium.base.ThreadUtils;
11import org.chromium.net.GURLUtils;
12
13import java.util.HashSet;
14import java.util.Set;
15
16/**
17 * This class is used to manage permissions for the WebView's Geolocation JavaScript API.
18 *
19 * Callbacks are posted on the UI thread.
20 */
21public final class AwGeolocationPermissions {
22
23    private static final String PREF_PREFIX =
24            "AwGeolocationPermissions%";
25    private final SharedPreferences mSharedPreferences;
26
27    public AwGeolocationPermissions(SharedPreferences sharedPreferences) {
28        mSharedPreferences = sharedPreferences;
29    }
30
31    /**
32     * Set one origin to be allowed.
33     */
34    public void allow(String origin) {
35        String key = getOriginKey(origin);
36        if (key != null) {
37            mSharedPreferences.edit().putBoolean(key, true).apply();
38        }
39    }
40
41    /**
42     * Set one origin to be denied.
43     */
44    public void deny(String origin) {
45        String key = getOriginKey(origin);
46        if (key != null) {
47            mSharedPreferences.edit().putBoolean(key, false).apply();
48        }
49    }
50
51    /**
52     * Clear the stored permission for a particular origin.
53     */
54    public void clear(String origin) {
55        String key = getOriginKey(origin);
56        if (key != null) {
57            mSharedPreferences.edit().remove(key).apply();
58        }
59    }
60
61    /**
62     * Clear stored permissions for all origins.
63     */
64    public void clearAll() {
65        SharedPreferences.Editor editor = null;
66        for (String name : mSharedPreferences.getAll().keySet()) {
67            if (name.startsWith(PREF_PREFIX)) {
68                if (editor == null) {
69                    editor = mSharedPreferences.edit();
70                }
71                editor.remove(name);
72            }
73        }
74        if (editor != null) {
75            editor.apply();
76        }
77    }
78
79    /**
80     * Synchronous method to get if an origin is set to be allowed.
81     */
82    public boolean isOriginAllowed(String origin) {
83        return mSharedPreferences.getBoolean(getOriginKey(origin), false);
84    }
85
86    /**
87     * Returns true if the origin is either set to allowed or denied.
88     */
89    public boolean hasOrigin(String origin) {
90        return mSharedPreferences.contains(getOriginKey(origin));
91    }
92
93    /**
94     * Asynchronous method to get if an origin set to be allowed.
95     */
96    public void getAllowed(String origin, final ValueCallback<Boolean> callback) {
97        final boolean finalAllowed = isOriginAllowed(origin);
98        ThreadUtils.postOnUiThread(new Runnable() {
99            @Override
100            public void run() {
101                callback.onReceiveValue(finalAllowed);
102            }
103        });
104    }
105
106    /**
107     * Async method to get the domains currently allowed or denied.
108     */
109    public void getOrigins(final ValueCallback<Set<String>> callback) {
110        final Set<String> origins = new HashSet<String>();
111        for (String name : mSharedPreferences.getAll().keySet()) {
112            if (name.startsWith(PREF_PREFIX)) {
113                origins.add(name.substring(PREF_PREFIX.length()));
114            }
115        }
116        ThreadUtils.postOnUiThread(new Runnable() {
117            @Override
118            public void run() {
119                callback.onReceiveValue(origins);
120            }
121        });
122    }
123
124    /**
125     * Get the domain of an URL using the GURL library.
126     */
127    private String getOriginKey(String url) {
128        String origin = GURLUtils.getOrigin(url);
129        if (origin.isEmpty()) {
130            return null;
131        }
132
133        return PREF_PREFIX + origin;
134    }
135}
136