OLD | NEW |
| (Empty) |
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.components.webrestrictions; | |
6 | |
7 import android.content.ContentProvider; | |
8 import android.content.ContentValues; | |
9 import android.content.Context; | |
10 import android.content.UriMatcher; | |
11 import android.content.pm.ProviderInfo; | |
12 import android.database.AbstractCursor; | |
13 import android.database.Cursor; | |
14 import android.net.Uri; | |
15 import android.util.Pair; | |
16 | |
17 import java.util.regex.Matcher; | |
18 import java.util.regex.Pattern; | |
19 | |
20 /** | |
21 * Abstract content provider for providing web restrictions, i.e. for providing
a filter for URLs so | |
22 * that they can be blocked or permitted, and a means of requesting permission f
or new URLs. It | |
23 * provides two (virtual) tables; an 'authorized' table listing the the status o
f every URL, and a | |
24 * 'requested' table containing the requests for access to new URLs. The 'author
ized' table is read | |
25 * only and the 'requested' table is write only. | |
26 */ | |
27 public abstract class WebRestrictionsContentProvider extends ContentProvider { | |
28 public static final int BLOCKED = 0; | |
29 public static final int PROCEED = 1; | |
30 private static final int WEB_RESTRICTIONS = 1; | |
31 private static final int AUTHORIZED = 2; | |
32 private static final int REQUESTED = 3; | |
33 | |
34 private final Pattern mSelectionPattern; | |
35 private UriMatcher mContentUriMatcher; | |
36 private Uri mContentUri; | |
37 | |
38 protected WebRestrictionsContentProvider() { | |
39 // Pattern to extract the URL from the selection. | |
40 // Matches patterns of the form "url = '<url>'" with arbitrary spacing a
round the "=" etc. | |
41 mSelectionPattern = Pattern.compile("\\s*url\\s*=\\s*'([^']*)'"); | |
42 } | |
43 | |
44 @Override | |
45 public boolean onCreate() { | |
46 return true; | |
47 } | |
48 | |
49 @Override | |
50 public void attachInfo(Context context, ProviderInfo info) { | |
51 super.attachInfo(context, info); | |
52 mContentUri = new Uri.Builder().scheme("content").authority(info.authori
ty).build(); | |
53 mContentUriMatcher = new UriMatcher(WEB_RESTRICTIONS); | |
54 mContentUriMatcher.addURI(info.authority, "authorized", AUTHORIZED); | |
55 mContentUriMatcher.addURI(info.authority, "requested", REQUESTED); | |
56 } | |
57 | |
58 @Override | |
59 public Cursor query(Uri uri, String[] projection, String selection, String[]
selectionArgs, | |
60 String sortOrder) { | |
61 if (!contentProviderEnabled()) return null; | |
62 // Check that this is the a query on the 'authorized' table | |
63 // TODO(aberent): Provide useful queries on the 'requested' table. | |
64 if (mContentUriMatcher.match(uri) != AUTHORIZED) return null; | |
65 // If the selection is of the right form get the url we are querying. | |
66 Matcher matcher = mSelectionPattern.matcher(selection); | |
67 if (!matcher.find()) return null; | |
68 final String url = matcher.group(1); | |
69 final Pair<Boolean, String> result = shouldProceed(url); | |
70 | |
71 return new AbstractCursor() { | |
72 | |
73 @Override | |
74 public int getCount() { | |
75 return 1; | |
76 } | |
77 | |
78 @Override | |
79 public String[] getColumnNames() { | |
80 return new String[] { | |
81 "Should Proceed", "Error message" | |
82 }; | |
83 } | |
84 | |
85 @Override | |
86 public String getString(int column) { | |
87 if (column == 1) return result.second; | |
88 return null; | |
89 } | |
90 | |
91 @Override | |
92 public short getShort(int column) { | |
93 return 0; | |
94 } | |
95 | |
96 @Override | |
97 public int getInt(int column) { | |
98 if (column == 0) return result.first ? PROCEED : BLOCKED; | |
99 return 0; | |
100 } | |
101 | |
102 @Override | |
103 public long getLong(int column) { | |
104 return 0; | |
105 } | |
106 | |
107 @Override | |
108 public float getFloat(int column) { | |
109 return 0; | |
110 } | |
111 | |
112 @Override | |
113 public double getDouble(int column) { | |
114 return 0; | |
115 } | |
116 | |
117 @Override | |
118 public boolean isNull(int column) { | |
119 return false; | |
120 } | |
121 }; | |
122 } | |
123 | |
124 @Override | |
125 public String getType(Uri uri) { | |
126 // Abused to return whether we can insert | |
127 if (!contentProviderEnabled()) return null; | |
128 if (mContentUriMatcher.match(uri) != REQUESTED) return null; | |
129 return canInsert() ? "text/plain" : null; | |
130 } | |
131 | |
132 @Override | |
133 public Uri insert(Uri uri, ContentValues values) { | |
134 if (!contentProviderEnabled()) return null; | |
135 if (mContentUriMatcher.match(uri) != REQUESTED) return null; | |
136 String url = values.getAsString("url"); | |
137 if (requestInsert(url)) { | |
138 // TODO(aberent): If we ever make the 'requested' table readable the
n we might want to | |
139 // change this to a more conventional content URI (with a row number
). | |
140 return uri.buildUpon().appendPath(url).build(); | |
141 } else { | |
142 return null; | |
143 } | |
144 } | |
145 | |
146 @Override | |
147 public int delete(Uri uri, String selection, String[] selectionArgs) { | |
148 return 0; | |
149 } | |
150 | |
151 @Override | |
152 public int update(Uri uri, ContentValues values, String selection, String[]
selectionArgs) { | |
153 return 0; | |
154 } | |
155 | |
156 /** | |
157 * @param url the URL that is wanted. | |
158 * @return a pair containing the Result and the HTML Error Message. result i
s true if safe to | |
159 * proceed, false otherwise. error message is only meaningful if res
ult is false, a null | |
160 * error message means use application default. | |
161 */ | |
162 protected abstract Pair<Boolean, String> shouldProceed(final String url); | |
163 | |
164 /** | |
165 * @return whether the content provider allows insertions. | |
166 */ | |
167 protected abstract boolean canInsert(); | |
168 | |
169 /** | |
170 * Start a request that a URL should be permitted | |
171 * | |
172 * @param url the URL that is wanted. | |
173 */ | |
174 protected abstract boolean requestInsert(final String url); | |
175 | |
176 /** | |
177 * @return true if the content provider is enabled, false if not | |
178 */ | |
179 protected abstract boolean contentProviderEnabled(); | |
180 | |
181 /** | |
182 * Call to tell observers that the filter has changed. | |
183 */ | |
184 protected void onFilterChanged() { | |
185 getContext().getContentResolver().notifyChange( | |
186 mContentUri.buildUpon().appendPath("authorized").build(), null); | |
187 } | |
188 } | |
OLD | NEW |