JniUtil.java revision 492bbe3f7b42860dafe5435203ea30278bf76b6c
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.InputStream; 26 27class JniUtil { 28 29 static { 30 System.loadLibrary("webcore"); 31 System.loadLibrary("chromium_net"); 32 } 33 private static final String LOGTAG = "webkit"; 34 private JniUtil() {} // Utility class, do not instantiate. 35 36 // Used by the Chromium HTTP stack. 37 private static String sDatabaseDirectory; 38 private static String sCacheDirectory; 39 private static Boolean sUseChromiumHttpStack; 40 private static Context sContext; 41 42 private static boolean initialized = false; 43 44 private static void checkInitialized() { 45 if (!initialized) { 46 throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class"); 47 } 48 } 49 50 protected static synchronized void setContext(Context context) { 51 if (initialized) 52 return; 53 54 sContext = context.getApplicationContext(); 55 initialized = true; 56 } 57 58 protected static synchronized Context getContext() { 59 if (!initialized) 60 return null; 61 return sContext; 62 } 63 64 /** 65 * Called by JNI. Gets the application's database directory, excluding the trailing slash. 66 * @return String The application's database directory 67 */ 68 private static synchronized String getDatabaseDirectory() { 69 checkInitialized(); 70 71 if (sDatabaseDirectory == null) 72 sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent(); 73 74 return sDatabaseDirectory; 75 } 76 77 /** 78 * Called by JNI. Gets the application's cache directory, excluding the trailing slash. 79 * @return String The application's cache directory 80 */ 81 private static synchronized String getCacheDirectory() { 82 checkInitialized(); 83 84 if (sCacheDirectory == null) 85 sCacheDirectory = sContext.getCacheDir().getAbsolutePath(); 86 87 return sCacheDirectory; 88 } 89 90 private static final String ANDROID_CONTENT = "content:"; 91 92 /** 93 * Called by JNI. Calculates the size of an input stream by reading it. 94 * @return long The size of the stream 95 */ 96 private static synchronized long contentUrlSize(String url) { 97 // content:// 98 if (url.startsWith(ANDROID_CONTENT)) { 99 try { 100 // Strip off mimetype, for compatibility with ContentLoader.java 101 // If we don't do this, we can fail to load Gmail attachments, 102 // because the URL being loaded doesn't exactly match the URL we 103 // have permission to read. 104 int mimeIndex = url.lastIndexOf('?'); 105 if (mimeIndex != -1) { 106 url = url.substring(0, mimeIndex); 107 } 108 Uri uri = Uri.parse(url); 109 InputStream is = sContext.getContentResolver().openInputStream(uri); 110 byte[] buffer = new byte[1024]; 111 int n; 112 long size = 0; 113 try { 114 while ((n = is.read(buffer)) != -1) { 115 size += n; 116 } 117 } finally { 118 is.close(); 119 } 120 return size; 121 } catch (Exception e) { 122 Log.e(LOGTAG, "Exception: " + url); 123 return 0; 124 } 125 } else { 126 return 0; 127 } 128 } 129 130 /** 131 * Called by JNI. 132 * 133 * @return Opened input stream to content 134 * TODO: Make all content loading use this instead of BrowserFrame.java 135 */ 136 private static synchronized InputStream contentUrlStream(String url) { 137 // content:// 138 if (url.startsWith(ANDROID_CONTENT)) { 139 try { 140 // Strip off mimetype, for compatibility with ContentLoader.java 141 // If we don't do this, we can fail to load Gmail attachments, 142 // because the URL being loaded doesn't exactly match the URL we 143 // have permission to read. 144 int mimeIndex = url.lastIndexOf('?'); 145 if (mimeIndex != -1) { 146 url = url.substring(0, mimeIndex); 147 } 148 Uri uri = Uri.parse(url); 149 return sContext.getContentResolver().openInputStream(uri); 150 } catch (Exception e) { 151 Log.e(LOGTAG, "Exception: " + url); 152 return null; 153 } 154 } else { 155 return null; 156 } 157 } 158 159 /** 160 * Returns true if we're using the Chromium HTTP stack. 161 * 162 * TODO: Remove this if/when we permanently switch to the Chromium HTTP stack 163 * http:/b/3118772 164 */ 165 static boolean useChromiumHttpStack() { 166 if (sUseChromiumHttpStack == null) { 167 sUseChromiumHttpStack = nativeUseChromiumHttpStack(); 168 } 169 return sUseChromiumHttpStack; 170 } 171 172 private static synchronized String getAutofillQueryUrl() { 173 checkInitialized(); 174 // If the device has not checked in it won't have pulled down the system setting for the 175 // Autofill Url. In that case we will not make autofill server requests. 176 return Settings.Secure.getString(sContext.getContentResolver(), 177 Settings.Secure.WEB_AUTOFILL_QUERY_URL); 178 } 179 180 private static boolean canSatisfyMemoryAllocation(long bytesRequested) { 181 checkInitialized(); 182 ActivityManager manager = (ActivityManager) sContext.getSystemService( 183 Context.ACTIVITY_SERVICE); 184 ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); 185 manager.getMemoryInfo(memInfo); 186 long leftToAllocate = memInfo.availMem - memInfo.threshold; 187 return !memInfo.lowMemory && bytesRequested < leftToAllocate; 188 } 189 190 191 private static native boolean nativeUseChromiumHttpStack(); 192} 193