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