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 17 package android.webkit; 18 19 import android.app.ActivityManager; 20 import android.content.Context; 21 import android.net.Uri; 22 import android.provider.Settings; 23 import android.util.Log; 24 25 import java.io.File; 26 import java.io.InputStream; 27 28 class JniUtil { 29 30 static { 31 System.loadLibrary("webcore"); 32 System.loadLibrary("chromium_net"); 33 } 34 private static final String LOGTAG = "webkit"; JniUtil()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 Context sContext; 41 checkInitialized()42 private static void checkInitialized() { 43 if (sContext == null) { 44 throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class"); 45 } 46 } 47 setContext(Context context)48 protected static synchronized void setContext(Context context) { 49 if (sContext != null) { 50 return; 51 } 52 53 sContext = context.getApplicationContext(); 54 } 55 getContext()56 protected static synchronized Context getContext() { 57 return sContext; 58 } 59 60 /** 61 * Called by JNI. Gets the application's database directory, excluding the trailing slash. 62 * @return String The application's database directory 63 */ getDatabaseDirectory()64 private static synchronized String getDatabaseDirectory() { 65 checkInitialized(); 66 67 if (sDatabaseDirectory == null) { 68 sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent(); 69 } 70 71 return sDatabaseDirectory; 72 } 73 74 /** 75 * Called by JNI. Gets the application's cache directory, excluding the trailing slash. 76 * @return String The application's cache directory 77 */ getCacheDirectory()78 private static synchronized String getCacheDirectory() { 79 checkInitialized(); 80 81 if (sCacheDirectory == null) { 82 File cacheDir = sContext.getCacheDir(); 83 if (cacheDir == null) { 84 sCacheDirectory = ""; 85 } else { 86 sCacheDirectory = cacheDir.getAbsolutePath(); 87 } 88 } 89 90 return sCacheDirectory; 91 } 92 93 /** 94 * Called by JNI. Gets the application's package name. 95 * @return String The application's package name 96 */ getPackageName()97 private static synchronized String getPackageName() { 98 checkInitialized(); 99 100 return sContext.getPackageName(); 101 } 102 103 private static final String ANDROID_CONTENT = URLUtil.CONTENT_BASE; 104 105 /** 106 * Called by JNI. Calculates the size of an input stream by reading it. 107 * @return long The size of the stream 108 */ contentUrlSize(String url)109 private static synchronized long contentUrlSize(String url) { 110 // content:// 111 if (url.startsWith(ANDROID_CONTENT)) { 112 try { 113 // Strip off MIME type. If we don't do this, we can fail to 114 // load Gmail attachments, because the URL being loaded doesn't 115 // exactly match the URL we have permission to read. 116 int mimeIndex = url.lastIndexOf('?'); 117 if (mimeIndex != -1) { 118 url = url.substring(0, mimeIndex); 119 } 120 Uri uri = Uri.parse(url); 121 InputStream is = sContext.getContentResolver().openInputStream(uri); 122 byte[] buffer = new byte[1024]; 123 int n; 124 long size = 0; 125 try { 126 while ((n = is.read(buffer)) != -1) { 127 size += n; 128 } 129 } finally { 130 is.close(); 131 } 132 return size; 133 } catch (Exception e) { 134 Log.e(LOGTAG, "Exception: " + url); 135 return 0; 136 } 137 } else { 138 return 0; 139 } 140 } 141 142 /** 143 * Called by JNI. 144 * 145 * @return Opened input stream to content 146 * TODO: Make all content loading use this instead of BrowserFrame.java 147 */ contentUrlStream(String url)148 private static synchronized InputStream contentUrlStream(String url) { 149 // content:// 150 if (url.startsWith(ANDROID_CONTENT)) { 151 try { 152 // Strip off mimetype, for compatibility with ContentLoader.java 153 // (used with Android HTTP stack, now removed). 154 // If we don't do this, we can fail to load Gmail attachments, 155 // because the URL being loaded doesn't exactly match the URL we 156 // have permission to read. 157 int mimeIndex = url.lastIndexOf('?'); 158 if (mimeIndex != -1) { 159 url = url.substring(0, mimeIndex); 160 } 161 Uri uri = Uri.parse(url); 162 return sContext.getContentResolver().openInputStream(uri); 163 } catch (Exception e) { 164 Log.e(LOGTAG, "Exception: " + url); 165 return null; 166 } 167 } else { 168 return null; 169 } 170 } 171 getAutofillQueryUrl()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 canSatisfyMemoryAllocation(long bytesRequested)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