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.chrome.browser.superviseduser; | |
6 | |
7 import android.os.Bundle; | |
8 import android.util.Pair; | |
9 | |
10 import org.chromium.base.ThreadUtils; | |
11 import org.chromium.base.VisibleForTesting; | |
12 import org.chromium.base.annotations.CalledByNative; | |
13 import org.chromium.base.library_loader.LibraryProcessType; | |
14 import org.chromium.base.library_loader.ProcessInitException; | |
15 import org.chromium.components.webrestriction.WebRestrictionsContentProvider; | |
16 import org.chromium.content.browser.BrowserStartupController; | |
17 | |
18 import java.util.concurrent.CountDownLatch; | |
19 | |
20 /** | |
21 * Content provider for telling other apps (e.g. WebView apps) about the supervi sed user URL filter. | |
22 */ | |
23 public class SupervisedUserContentProvider extends WebRestrictionsContentProvide r { | |
24 private long mNativeSupervisedUserContentProvider = 0; | |
25 | |
26 private long getSupervisedUserContentProvider() throws ProcessInitException { | |
27 if (mNativeSupervisedUserContentProvider != 0) { | |
28 return mNativeSupervisedUserContentProvider; | |
29 } | |
30 | |
31 BrowserStartupController.get(getContext(), LibraryProcessType.PROCESS_BR OWSER) | |
32 .startBrowserProcessesSync(false); | |
33 | |
34 mNativeSupervisedUserContentProvider = nativeCreateSupervisedUserContent Provider(); | |
35 return mNativeSupervisedUserContentProvider; | |
36 } | |
37 | |
38 @VisibleForTesting | |
39 void setNativeSupervisedUserContentProviderForTesting(long nativeProvider) { | |
40 mNativeSupervisedUserContentProvider = nativeProvider; | |
41 } | |
42 | |
43 @VisibleForTesting | |
44 static class SupervisedUserQueryReply { | |
45 final CountDownLatch mLatch = new CountDownLatch(1); | |
46 private Pair<Boolean, String> mResult; | |
47 @VisibleForTesting | |
48 @CalledByNative("SupervisedUserQueryReply") | |
49 void onQueryComplete(boolean result, String errorMessage) { | |
50 // This must be called precisely once per query. | |
51 assert mResult == null; | |
52 mResult = new Pair<Boolean, String>(result, errorMessage); | |
53 mLatch.countDown(); | |
54 } | |
55 Pair<Boolean, String> getResult() throws InterruptedException { | |
56 mLatch.await(); | |
57 return mResult; | |
58 } | |
59 } | |
60 | |
61 @Override | |
62 protected Pair<Boolean, String> shouldProceed(final String url) { | |
63 // This will be called on multiple threads (but never the UI thread), | |
64 // see http://developer.android.com/guide/components/processes-and-threa ds.html#ThreadSafe. | |
65 // The reply comes back on a different thread (possibly the UI thread) s ome time later. | |
66 // As such it needs to correctly match the replies to the calls. It does this by creating a | |
67 // reply object for each query, and passing this through the callback st ructure. The reply | |
68 // object also handles waiting for the reply. | |
69 assert !ThreadUtils.runningOnUiThread(); | |
Bernhard Bauer
2016/01/05 10:22:32
Actually... if everything but this works without u
aberent
2016/01/05 10:48:38
On further thought this assertion no longer makes
| |
70 final SupervisedUserQueryReply queryReply = new SupervisedUserQueryReply (); | |
71 ThreadUtils.runOnUiThread(new Runnable() { | |
72 @Override | |
73 public void run() { | |
74 try { | |
75 nativeShouldProceed(getSupervisedUserContentProvider(), quer yReply, url); | |
76 } catch (ProcessInitException e) { | |
77 queryReply.onQueryComplete(false, null); | |
78 } | |
79 } | |
80 }); | |
81 try { | |
82 // This will block until an onQueryComplete call on a different thre ad adds | |
83 // something to the queue. | |
84 return queryReply.getResult(); | |
85 } catch (InterruptedException e) { | |
86 return new Pair<Boolean, String>(false, null); | |
87 } | |
88 } | |
89 | |
90 @Override | |
91 protected boolean canInsert() { | |
92 // Chrome always allows insertion requests. | |
93 return true; | |
94 } | |
95 | |
96 @VisibleForTesting | |
97 static class SupervisedUserInsertReply { | |
98 final CountDownLatch mLatch = new CountDownLatch(1); | |
99 boolean mResult; | |
100 @VisibleForTesting | |
101 @CalledByNative("SupervisedUserInsertReply") | |
102 void onInsertRequestSendComplete(boolean result) { | |
103 // This must be called precisely once per query. | |
104 assert mLatch.getCount() == 1; | |
105 mResult = result; | |
106 mLatch.countDown(); | |
107 } | |
108 boolean getResult() throws InterruptedException { | |
109 mLatch.await(); | |
110 return mResult; | |
111 } | |
112 } | |
113 | |
114 @Override | |
115 protected boolean requestInsert(final String url) { | |
116 // This will be called on multiple threads (but never the UI thread), | |
117 // see http://developer.android.com/guide/components/processes-and-threa ds.html#ThreadSafe. | |
118 // The reply comes back on a different thread (possibly the UI thread) s ome time later. | |
119 // As such it needs to correctly match the replies to the calls. It does this by creating a | |
120 // reply object for each query, and passing this through the callback st ructure. The reply | |
121 // object also handles waiting for the reply. | |
122 assert !ThreadUtils.runningOnUiThread(); | |
123 final SupervisedUserInsertReply insertReply = new SupervisedUserInsertRe ply(); | |
124 ThreadUtils.runOnUiThread(new Runnable() { | |
125 @Override | |
126 public void run() { | |
127 try { | |
128 nativeRequestInsert(getSupervisedUserContentProvider(), inse rtReply, url); | |
129 } catch (ProcessInitException e) { | |
130 insertReply.onInsertRequestSendComplete(false); | |
131 } | |
132 } | |
133 }); | |
134 try { | |
135 return insertReply.getResult(); | |
136 } catch (InterruptedException e) { | |
137 return false; | |
138 } | |
139 } | |
140 | |
141 @VisibleForTesting | |
142 @Override | |
143 public Bundle call(String method, String arg, Bundle bundle) { | |
144 if (method.equals("setFilterForTesting")) setFilterForTesting(); | |
145 return null; | |
146 } | |
147 | |
148 @VisibleForTesting | |
149 void setFilterForTesting() { | |
150 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
151 @Override | |
152 public void run() { | |
153 try { | |
154 nativeSetFilterForTesting(getSupervisedUserContentProvider() ); | |
155 } catch (ProcessInitException e) { | |
156 // There is no way of returning anything sensible here, so i gnore the error and | |
157 // do nothing. | |
158 } | |
159 } | |
160 }); | |
161 } | |
162 | |
163 @VisibleForTesting | |
164 @CalledByNative | |
165 void onSupervisedUserFilterUpdated() { | |
166 onFilterChanged(); | |
167 } | |
168 | |
169 @VisibleForTesting native long nativeCreateSupervisedUserContentProvider(); | |
170 | |
171 @VisibleForTesting | |
172 native void nativeShouldProceed(long nativeSupervisedUserContentProvider, | |
173 SupervisedUserQueryReply queryReply, String url); | |
174 | |
175 @VisibleForTesting | |
176 native void nativeRequestInsert(long nativeSupervisedUserContentProvider, | |
177 SupervisedUserInsertReply insertReply, String url); | |
178 | |
179 private native void nativeSetFilterForTesting(long nativeSupervisedUserConte ntProvider); | |
180 } | |
OLD | NEW |