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 5package org.chromium.android_webview.test; 6 7import android.test.suitebuilder.annotation.LargeTest; 8import android.util.Pair; 9import android.webkit.ValueCallback; 10 11import org.chromium.android_webview.AwContents; 12import org.chromium.android_webview.AwQuotaManagerBridge; 13import org.chromium.android_webview.AwSettings; 14import org.chromium.android_webview.test.util.AwQuotaManagerBridgeTestUtil; 15import org.chromium.base.test.util.Feature; 16import org.chromium.content.browser.test.util.CallbackHelper; 17import org.chromium.net.test.util.TestWebServer; 18 19import java.util.ArrayList; 20import java.util.List; 21import java.util.concurrent.Callable; 22 23/** 24 * Tests for the AwQuotaManagerBridge. 25 */ 26public class AwQuotaManagerBridgeTest extends AwTestBase { 27 private TestAwContentsClient mContentsClient; 28 private AwTestContainerView mTestView; 29 private AwContents mAwContents; 30 private TestWebServer mWebServer; 31 private String mOrigin; 32 33 @Override 34 public void setUp() throws Exception { 35 super.setUp(); 36 mContentsClient = new TestAwContentsClient(); 37 mTestView = createAwTestContainerViewOnMainSync(mContentsClient); 38 mAwContents = mTestView.getAwContents(); 39 mWebServer = new TestWebServer(false); 40 mOrigin = mWebServer.getBaseUrl(); 41 42 AwSettings settings = getAwSettingsOnUiThread(mAwContents); 43 settings.setJavaScriptEnabled(true); 44 settings.setDomStorageEnabled(true); 45 settings.setAppCacheEnabled(true); 46 settings.setAppCachePath("whatever"); // Enables AppCache. 47 } 48 49 @Override 50 public void tearDown() throws Exception { 51 deleteAllData(); 52 if (mWebServer != null) { 53 mWebServer.shutdown(); 54 } 55 super.tearDown(); 56 } 57 58 private void deleteAllData() throws Exception { 59 final AwQuotaManagerBridge bridge = 60 AwQuotaManagerBridgeTestUtil.getQuotaManagerBridge(this); 61 getInstrumentation().runOnMainSync(new Runnable() { 62 @Override 63 public void run() { 64 bridge.deleteAllData(); 65 } 66 }); 67 } 68 69 private void deleteOrigin(final String origin) throws Exception { 70 final AwQuotaManagerBridge bridge = 71 AwQuotaManagerBridgeTestUtil.getQuotaManagerBridge(this); 72 getInstrumentation().runOnMainSync(new Runnable() { 73 @Override 74 public void run() { 75 bridge.deleteOrigin(origin); 76 } 77 }); 78 } 79 80 private static class LongValueCallbackHelper extends CallbackHelper { 81 private long mValue; 82 83 public void notifyCalled(long value) { 84 mValue = value; 85 notifyCalled(); 86 } 87 88 public long getValue() { 89 assert getCallCount() > 0; 90 return mValue; 91 } 92 } 93 94 private long getQuotaForOrigin(final String origin) throws Exception { 95 final LongValueCallbackHelper callbackHelper = new LongValueCallbackHelper(); 96 final AwQuotaManagerBridge bridge = 97 AwQuotaManagerBridgeTestUtil.getQuotaManagerBridge(this); 98 99 int callCount = callbackHelper.getCallCount(); 100 getInstrumentation().runOnMainSync(new Runnable() { 101 @Override 102 public void run() { 103 bridge.getQuotaForOrigin("foo.com", 104 new ValueCallback<Long>() { 105 @Override 106 public void onReceiveValue(Long quota) { 107 callbackHelper.notifyCalled(quota); 108 } 109 } 110 ); 111 } 112 }); 113 callbackHelper.waitForCallback(callCount); 114 115 return callbackHelper.getValue(); 116 } 117 118 private long getUsageForOrigin(final String origin) throws Exception { 119 final LongValueCallbackHelper callbackHelper = new LongValueCallbackHelper(); 120 final AwQuotaManagerBridge bridge = 121 AwQuotaManagerBridgeTestUtil.getQuotaManagerBridge(this); 122 123 int callCount = callbackHelper.getCallCount(); 124 getInstrumentation().runOnMainSync(new Runnable() { 125 @Override 126 public void run() { 127 bridge.getUsageForOrigin(origin, 128 new ValueCallback<Long>() { 129 @Override 130 public void onReceiveValue(Long usage) { 131 callbackHelper.notifyCalled(usage); 132 } 133 } 134 ); 135 } 136 }); 137 callbackHelper.waitForCallback(callCount); 138 139 return callbackHelper.getValue(); 140 } 141 142 private void useAppCache() throws Exception { 143 final String cachedFilePath = "/foo.js"; 144 final String cachedFileContents = "1 + 1;"; 145 mWebServer.setResponse(cachedFilePath, cachedFileContents, null); 146 147 final String manifestPath = "/foo.manifest"; 148 final String manifestContents = "CACHE MANIFEST\nCACHE:\n" + cachedFilePath; 149 List<Pair<String, String>> manifestHeaders = new ArrayList<Pair<String, String>>(); 150 manifestHeaders.add(Pair.create("Content-Disposition", "text/cache-manifest")); 151 mWebServer.setResponse(manifestPath, manifestContents, manifestHeaders); 152 153 final String pagePath = "/appcache.html"; 154 final String pageContents = "<html manifest=\"" + manifestPath + "\">" + 155 "<head><script src=\"" + cachedFilePath + "\"></script></head></html>"; 156 String url = mWebServer.setResponse(pagePath, pageContents, null); 157 158 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), url); 159 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, 160 "window.applicationCache.update();"); 161 } 162 163 @LargeTest 164 @Feature({"AndroidWebView", "WebStore"}) 165 public void testDeleteAllWithAppCache() throws Exception { 166 final long initialUsage = getUsageForOrigin(mOrigin); 167 168 useAppCache(); 169 poll(new Callable<Boolean>() { 170 @Override 171 public Boolean call() throws Exception { 172 return getUsageForOrigin(mOrigin) > initialUsage; 173 } 174 }); 175 176 deleteAllData(); 177 poll(new Callable<Boolean>() { 178 @Override 179 public Boolean call() throws Exception { 180 return getUsageForOrigin(mOrigin) == 0; 181 } 182 }); 183 } 184 185 @LargeTest 186 @Feature({"AndroidWebView", "WebStore"}) 187 public void testDeleteOriginWithAppCache() throws Exception { 188 final long initialUsage = getUsageForOrigin(mOrigin); 189 190 useAppCache(); 191 poll(new Callable<Boolean>() { 192 @Override 193 public Boolean call() throws Exception { 194 return getUsageForOrigin(mOrigin) > initialUsage; 195 } 196 }); 197 198 deleteOrigin(mOrigin); 199 poll(new Callable<Boolean>() { 200 @Override 201 public Boolean call() throws Exception { 202 return getUsageForOrigin(mOrigin) == 0; 203 } 204 }); 205 } 206 207 @LargeTest 208 @Feature({"AndroidWebView", "WebStore"}) 209 public void testGetResultsMatch() throws Exception { 210 useAppCache(); 211 212 poll(new Callable<Boolean>() { 213 @Override 214 public Boolean call() throws Exception { 215 return AwQuotaManagerBridgeTestUtil.getOrigins( 216 AwQuotaManagerBridgeTest.this).mOrigins.length > 0; 217 } 218 }); 219 220 AwQuotaManagerBridge.Origins origins = AwQuotaManagerBridgeTestUtil.getOrigins(this); 221 assertEquals(origins.mOrigins.length, origins.mUsages.length); 222 assertEquals(origins.mOrigins.length, origins.mQuotas.length); 223 224 for (int i = 0; i < origins.mOrigins.length; ++i) { 225 assertEquals(origins.mUsages[i], getUsageForOrigin(origins.mOrigins[i])); 226 assertEquals(origins.mQuotas[i], getQuotaForOrigin(origins.mOrigins[i])); 227 } 228 } 229} 230