1 | // Copyright (c) 2013 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.android_webview; |
6 | |
7 | import org.chromium.base.CalledByNative; |
8 | import org.chromium.base.JNINamespace; |
9 | import org.chromium.base.ThreadUtils; |
10 | |
11 | import android.webkit.ValueCallback; |
12 | |
13 | import java.util.Map; |
14 | import java.util.HashMap; |
15 | |
16 | /** |
17 | * Bridge between android.webview.WebStorage and native QuotaManager. This object is owned by Java |
18 | * AwBrowserContext and the native side is owned by the native AwBrowserContext. |
19 | * |
20 | * TODO(boliu): Actually make this true after Java AwBrowserContext is added. |
21 | */ |
22 | @JNINamespace("android_webview") |
23 | public class AwQuotaManagerBridge { |
24 | // TODO(boliu): This should be obtained from Java AwBrowserContext that owns this. |
25 | private static native int nativeGetDefaultNativeAwQuotaManagerBridge(); |
26 | |
27 | // TODO(boliu): This should be owned by Java AwBrowserContext, not a singleton. |
28 | private static AwQuotaManagerBridge sInstance; |
29 | public static AwQuotaManagerBridge getInstance() { |
30 | ThreadUtils.assertOnUiThread(); |
31 | if (sInstance == null) { |
32 | sInstance = new AwQuotaManagerBridge(nativeGetDefaultNativeAwQuotaManagerBridge()); |
33 | } |
34 | return sInstance; |
35 | } |
36 | |
37 | /** |
38 | * This class represent the callback value of android.webview.WebStorage.getOrigins. The values |
39 | * are optimized for JNI convenience and need to be converted. |
40 | */ |
41 | public static class Origins { |
42 | // Origin, usage, and quota data in parallel arrays of same length. |
43 | public final String[] mOrigins; |
44 | public final long[] mUsages; |
45 | public final long[] mQuotas; |
46 | |
47 | Origins(String[] origins, long[] usages, long[] quotas) { |
48 | mOrigins = origins; |
49 | mUsages = usages; |
50 | mQuotas = quotas; |
51 | } |
52 | } |
53 | |
54 | // This is not owning. The native object is owned by the native AwBrowserContext. |
55 | private int mNativeAwQuotaManagerBridgeImpl; |
56 | |
57 | // The Java callbacks are saved here. An incrementing callback id is generated for each saved |
58 | // callback and is passed to the native side to identify callback. |
59 | private int mNextId; |
60 | private Map<Integer, ValueCallback<Origins>> mPendingGetOriginCallbacks; |
61 | private Map<Integer, ValueCallback<Long>> mPendingGetQuotaForOriginCallbacks; |
62 | private Map<Integer, ValueCallback<Long>> mPendingGetUsageForOriginCallbacks; |
63 | |
64 | private AwQuotaManagerBridge(int nativeAwQuotaManagerBridgeImpl) { |
65 | mNativeAwQuotaManagerBridgeImpl = nativeAwQuotaManagerBridgeImpl; |
66 | mPendingGetOriginCallbacks = |
67 | new HashMap<Integer, ValueCallback<Origins>>(); |
68 | mPendingGetQuotaForOriginCallbacks = new HashMap<Integer, ValueCallback<Long>>(); |
69 | mPendingGetUsageForOriginCallbacks = new HashMap<Integer, ValueCallback<Long>>(); |
70 | nativeInit(mNativeAwQuotaManagerBridgeImpl); |
71 | } |
72 | |
73 | private int getNextId() { |
74 | ThreadUtils.assertOnUiThread(); |
75 | return ++mNextId; |
76 | } |
77 | |
78 | /* |
79 | * There are five HTML5 offline storage APIs. |
80 | * 1) Web Storage (ie the localStorage and sessionStorage variables) |
81 | * 2) Web SQL database |
82 | * 3) Application cache |
83 | * 4) Indexed Database |
84 | * 5) Filesystem API |
85 | */ |
86 | |
87 | /** |
88 | * Implements WebStorage.deleteAllData(). Clear the storage of all five offline APIs. |
89 | * |
90 | * TODO(boliu): Actually clear Web Storage. |
91 | */ |
92 | public void deleteAllData() { |
93 | nativeDeleteAllData(mNativeAwQuotaManagerBridgeImpl); |
94 | } |
95 | |
96 | /** |
97 | * Implements WebStorage.deleteOrigin(). Clear the storage of APIs 2-5 for the given origin. |
98 | */ |
99 | public void deleteOrigin(String origin) { |
100 | nativeDeleteOrigin(mNativeAwQuotaManagerBridgeImpl, origin); |
101 | } |
102 | |
103 | /** |
104 | * Implements WebStorage.getOrigins. Get the per origin usage and quota of APIs 2-5 in |
105 | * aggregate. |
106 | */ |
107 | public void getOrigins(ValueCallback<Origins> callback) { |
108 | int callbackId = getNextId(); |
109 | assert !mPendingGetOriginCallbacks.containsKey(callbackId); |
110 | mPendingGetOriginCallbacks.put(callbackId, callback); |
111 | nativeGetOrigins(mNativeAwQuotaManagerBridgeImpl, callbackId); |
112 | } |
113 | |
114 | /** |
115 | * Implements WebStorage.getQuotaForOrigin. Get the quota of APIs 2-5 in aggregate for given |
116 | * origin. |
117 | */ |
118 | public void getQuotaForOrigin(String origin, ValueCallback<Long> callback) { |
119 | int callbackId = getNextId(); |
120 | assert !mPendingGetQuotaForOriginCallbacks.containsKey(callbackId); |
121 | mPendingGetQuotaForOriginCallbacks.put(callbackId, callback); |
122 | nativeGetUsageAndQuotaForOrigin(mNativeAwQuotaManagerBridgeImpl, origin, callbackId, true); |
123 | } |
124 | |
125 | /** |
126 | * Implements WebStorage.getUsageForOrigin. Get the usage of APIs 2-5 in aggregate for given |
127 | * origin. |
128 | */ |
129 | public void getUsageForOrigin(String origin, ValueCallback<Long> callback) { |
130 | int callbackId = getNextId(); |
131 | assert !mPendingGetUsageForOriginCallbacks.containsKey(callbackId); |
132 | mPendingGetUsageForOriginCallbacks.put(callbackId, callback); |
133 | nativeGetUsageAndQuotaForOrigin(mNativeAwQuotaManagerBridgeImpl, origin, callbackId, false); |
134 | } |
135 | |
136 | @CalledByNative |
137 | private void onGetOriginsCallback(int callbackId, String[] origin, long[] usages, |
138 | long[] quotas) { |
139 | assert mPendingGetOriginCallbacks.containsKey(callbackId); |
140 | mPendingGetOriginCallbacks.remove(callbackId).onReceiveValue( |
141 | new Origins(origin, usages, quotas)); |
142 | } |
143 | |
144 | @CalledByNative |
145 | private void onGetUsageAndQuotaForOriginCallback( |
146 | int callbackId, boolean isQuota, long usage, long quota) { |
147 | if (isQuota) { |
148 | assert mPendingGetQuotaForOriginCallbacks.containsKey(callbackId); |
149 | mPendingGetQuotaForOriginCallbacks.remove(callbackId).onReceiveValue(quota); |
150 | } else { |
151 | assert mPendingGetUsageForOriginCallbacks.containsKey(callbackId); |
152 | mPendingGetUsageForOriginCallbacks.remove(callbackId).onReceiveValue(usage); |
153 | } |
154 | } |
155 | |
156 | private native void nativeInit(int nativeAwQuotaManagerBridgeImpl); |
157 | private native void nativeDeleteAllData(int nativeAwQuotaManagerBridgeImpl); |
158 | private native void nativeDeleteOrigin(int nativeAwQuotaManagerBridgeImpl, String origin); |
159 | private native void nativeGetOrigins(int nativeAwQuotaManagerBridgeImpl, int callbackId); |
160 | private native void nativeGetUsageAndQuotaForOrigin(int nativeAwQuotaManagerBridgeImpl, |
161 | String origin, int callbackId, boolean isQuota); |
162 | } |