JniUtil.java revision 0d491c1dce964ee94a805c595fbf589dbbb2902e
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.webkit; 18 19import android.app.ActivityManager; 20import android.content.Context; 21import android.net.Uri; 22import android.provider.Settings; 23import android.util.Log; 24 25import java.io.File; 26import java.io.InputStream; 27 28class JniUtil { 29 30 static { 31 System.loadLibrary("webcore"); 32 System.loadLibrary("chromium_net"); 33 } 34 private static final String LOGTAG = "webkit"; 35 private JniUtil() {} // Utility class, do not instantiate. 36 37 // Used by the Chromium HTTP stack. 38 private static String sDatabaseDirectory; 39 private static String sCacheDirectory; 40 private static Boolean sUseChromiumHttpStack; 41 private static Context sContext; 42 43 private static void checkInitialized() { 44 if (sContext == null) { 45 throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class"); 46 } 47 } 48 49 protected static synchronized void setContext(Context context) { 50 if (sContext != null) { 51 return; 52 } 53 54 sContext = context.getApplicationContext(); 55 } 56 57 protected static synchronized Context getContext() { 58 return sContext; 59 } 60 61 /** 62 * Called by JNI. Gets the application's database directory, excluding the trailing slash. 63 * @return String The application's database directory 64 */ 65 private static synchronized String getDatabaseDirectory() { 66 checkInitialized(); 67 68 if (sDatabaseDirectory == null) { 69 sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent(); 70 } 71 72 return sDatabaseDirectory; 73 } 74 75 /** 76 * Called by JNI. Gets the application's cache directory, excluding the trailing slash. 77 * @return String The application's cache directory 78 */ 79 private static synchronized String getCacheDirectory() { 80 checkInitialized(); 81 82 if (sCacheDirectory == null) { 83 File cacheDir = sContext.getCacheDir(); 84 if (cacheDir == null) { 85 sCacheDirectory = ""; 86 } else { 87 sCacheDirectory = cacheDir.getAbsolutePath(); 88 } 89 } 90 91 return sCacheDirectory; 92 } 93 94 private static final String ANDROID_CONTENT = "content:"; 95 96 /** 97 * Called by JNI. Calculates the size of an input stream by reading it. 98 * @return long The size of the stream 99 */ 100 private static synchronized long contentUrlSize(String url) { 101 // content:// 102 if (url.startsWith(ANDROID_CONTENT)) { 103 try { 104 // Strip off mimetype, for compatibility with ContentLoader.java 105 // If we don't do this, we can fail to load Gmail attachments, 106 // because the URL being loaded doesn't exactly match the URL we 107 // have permission to read. 108 int mimeIndex = url.lastIndexOf('?'); 109 if (mimeIndex != -1) { 110 url = url.substring(0, mimeIndex); 111 } 112 Uri uri = Uri.parse(url); 113 InputStream is = sContext.getContentResolver().openInputStream(uri); 114 byte[] buffer = new byte[1024]; 115 int n; 116 long size = 0; 117 try { 118 while ((n = is.read(buffer)) != -1) { 119 size += n; 120 } 121 } finally { 122 is.close(); 123 } 124 return size; 125 } catch (Exception e) { 126 Log.e(LOGTAG, "Exception: " + url); 127 return 0; 128 } 129 } else { 130 return 0; 131 } 132 } 133 134 /** 135 * Called by JNI. 136 * 137 * @return Opened input stream to content 138 * TODO: Make all content loading use this instead of BrowserFrame.java 139 */ 140 private static synchronized InputStream contentUrlStream(String url) { 141 // content:// 142 if (url.startsWith(ANDROID_CONTENT)) { 143 try { 144 // Strip off mimetype, for compatibility with ContentLoader.java 145 // If we don't do this, we can fail to load Gmail attachments, 146 // because the URL being loaded doesn't exactly match the URL we 147 // have permission to read. 148 int mimeIndex = url.lastIndexOf('?'); 149 if (mimeIndex != -1) { 150 url = url.substring(0, mimeIndex); 151 } 152 Uri uri = Uri.parse(url); 153 return sContext.getContentResolver().openInputStream(uri); 154 } catch (Exception e) { 155 Log.e(LOGTAG, "Exception: " + url); 156 return null; 157 } 158 } else { 159 return null; 160 } 161 } 162 163 /** 164 * Returns true if we're using the Chromium HTTP stack. 165 * 166 * TODO: Remove this if/when we permanently switch to the Chromium HTTP stack 167 * http:/b/3118772 168 */ 169 static boolean useChromiumHttpStack() { 170 if (sUseChromiumHttpStack == null) { 171 sUseChromiumHttpStack = nativeUseChromiumHttpStack(); 172 } 173 return sUseChromiumHttpStack; 174 } 175 176 private static synchronized String getAutofillQueryUrl() { 177 checkInitialized(); 178 // If the device has not checked in it won't have pulled down the system setting for the 179 // Autofill Url. In that case we will not make autofill server requests. 180 return Settings.Secure.getString(sContext.getContentResolver(), 181 Settings.Secure.WEB_AUTOFILL_QUERY_URL); 182 } 183 184 private static boolean canSatisfyMemoryAllocation(long bytesRequested) { 185 checkInitialized(); 186 ActivityManager manager = (ActivityManager) sContext.getSystemService( 187 Context.ACTIVITY_SERVICE); 188 ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); 189 manager.getMemoryInfo(memInfo); 190 long leftToAllocate = memInfo.availMem - memInfo.threshold; 191 return !memInfo.lowMemory && bytesRequested < leftToAllocate; 192 } 193 194 195 private static native boolean nativeUseChromiumHttpStack(); 196} 197