Drop support for Android HTTP stack
All future releases will use the Chromium HTTP stack and maintaining two HTTP
stacks adds maintenance overhead. The Chromium HTTP stack requires V8, but we
now use V8 in all build targets (b/5495373), so we can safely drop the Android
HTTP stack.
LoadListener, HttpAuthHandlerImpl, Network, SslErrorHandlerImpl, WebViewWorker
- Android-stack specific, removed
StreamLoader, FrameLoader
- Require LoadListener, removed
CacheLoader, ContentLoader, DataLoader, FileLoader
- Extend StreamLoader, removed
BrowserFrame
- Removed methods that create LoadListener
- BrowserFrame.startLoadingResource() is called from native
CallbackProxy, WebView
- Removed calls to Network methods
CacheManager, CookieManager, CookieSyncManager, WebViewCore, WebResourceResponse
- Removed other Android-stack specific code
JniUtlil
- Removed useChromiumHttpStack()
WebViewDatabase
- Removed all code to create cookies and cache databases for Android HTTP stack
See corresponding WebKit change https://android-git.corp.google.com/g/166327.
Bug: 5495616
Change-Id: If491675516f6eb187077af4220214bb6e6a8d045
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 3613ec9..8ccc59c7 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -471,18 +471,6 @@
}
/**
- * We have received an SSL certificate for the main top-level page.
- * Used by the Android HTTP stack only.
- */
- void certificate(SslCertificate certificate) {
- if (mIsMainFrame) {
- // we want to make this call even if the certificate is null
- // (ie, the site is not secure)
- mCallbackProxy.onReceivedCertificate(certificate);
- }
- }
-
- /**
* Destroy all native components of the BrowserFrame.
*/
public void destroy() {
@@ -515,10 +503,6 @@
}
}
}
- if (!JniUtil.useChromiumHttpStack()) {
- WebViewWorker.getHandler().sendEmptyMessage(
- WebViewWorker.MSG_TRIM_CACHE);
- }
break;
}
@@ -767,10 +751,9 @@
} else if (mSettings.getAllowContentAccess() &&
url.startsWith(ANDROID_CONTENT)) {
try {
- // Strip off mimetype, for compatibility with ContentLoader.java
- // If we don't do this, we can fail to load Gmail attachments,
- // because the URL being loaded doesn't exactly match the URL we
- // have permission to read.
+ // Strip off MIME type. If we don't do this, we can fail to
+ // load Gmail attachments, because the URL being loaded doesn't
+ // exactly match the URL we have permission to read.
int mimeIndex = url.lastIndexOf('?');
if (mimeIndex != -1) {
url = url.substring(0, mimeIndex);
@@ -787,101 +770,11 @@
}
/**
- * Start loading a resource.
- * @param loaderHandle The native ResourceLoader that is the target of the
- * data.
- * @param url The url to load.
- * @param method The http method.
- * @param headers The http headers.
- * @param postData If the method is "POST" postData is sent as the request
- * body. Is null when empty.
- * @param postDataIdentifier If the post data contained form this is the form identifier, otherwise it is 0.
- * @param cacheMode The cache mode to use when loading this resource. See WebSettings.setCacheMode
- * @param mainResource True if the this resource is the main request, not a supporting resource
- * @param userGesture
- * @param synchronous True if the load is synchronous.
- * @return A newly created LoadListener object.
- */
- private LoadListener startLoadingResource(int loaderHandle,
- String url,
- String method,
- HashMap headers,
- byte[] postData,
- long postDataIdentifier,
- int cacheMode,
- boolean mainResource,
- boolean userGesture,
- boolean synchronous,
- String username,
- String password) {
- if (mSettings.getCacheMode() != WebSettings.LOAD_DEFAULT) {
- cacheMode = mSettings.getCacheMode();
- }
-
- if (method.equals("POST")) {
- // Don't use the cache on POSTs when issuing a normal POST
- // request.
- if (cacheMode == WebSettings.LOAD_NORMAL) {
- cacheMode = WebSettings.LOAD_NO_CACHE;
- }
- String[] ret = getUsernamePassword();
- if (ret != null) {
- String domUsername = ret[0];
- String domPassword = ret[1];
- maybeSavePassword(postData, domUsername, domPassword);
- }
- }
-
- // is this resource the main-frame top-level page?
- boolean isMainFramePage = mIsMainFrame;
-
- if (DebugFlags.BROWSER_FRAME) {
- Log.v(LOGTAG, "startLoadingResource: url=" + url + ", method="
- + method + ", postData=" + postData + ", isMainFramePage="
- + isMainFramePage + ", mainResource=" + mainResource
- + ", userGesture=" + userGesture);
- }
-
- // Create a LoadListener
- LoadListener loadListener = LoadListener.getLoadListener(mContext,
- this, url, loaderHandle, synchronous, isMainFramePage,
- mainResource, userGesture, postDataIdentifier, username, password);
-
- if (LoadListener.getNativeLoaderCount() > MAX_OUTSTANDING_REQUESTS) {
- // send an error message, so that loadListener can be deleted
- // after this is returned. This is important as LoadListener's
- // nativeError will remove the request from its DocLoader's request
- // list. But the set up is not done until this method is returned.
- loadListener.error(
- android.net.http.EventHandler.ERROR, mContext.getString(
- com.android.internal.R.string.httpErrorTooManyRequests));
- return loadListener;
- }
-
- // Note that we are intentionally skipping
- // inputStreamForAndroidResource. This is so that FrameLoader will use
- // the various StreamLoader classes to handle assets.
- FrameLoader loader = new FrameLoader(loadListener, mSettings, method,
- mCallbackProxy.shouldInterceptRequest(url));
- loader.setHeaders(headers);
- loader.setPostData(postData);
- // Set the load mode to the mode used for the current page.
- // If WebKit wants validation, go to network directly.
- loader.setCacheMode(headers.containsKey("If-Modified-Since")
- || headers.containsKey("If-None-Match") ?
- WebSettings.LOAD_NO_CACHE : cacheMode);
- loader.executeLoad();
- // Set referrer to current URL?
- return !synchronous ? loadListener : null;
- }
-
- /**
* If this looks like a POST request (form submission) containing a username
* and password, give the user the option of saving them. Will either do
* nothing, or block until the UI interaction is complete.
*
- * Called by startLoadingResource when using the Apache HTTP stack.
- * Called directly by WebKit when using the Chrome HTTP stack.
+ * Called directly by WebKit.
*
* @param postData The data about to be sent as the body of a POST request.
* @param username The username entered by the user (sniffed from the DOM).
diff --git a/core/java/android/webkit/CacheLoader.java b/core/java/android/webkit/CacheLoader.java
deleted file mode 100644
index 0721045..0000000
--- a/core/java/android/webkit/CacheLoader.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.Headers;
-import android.text.TextUtils;
-import android.webkit.JniUtil;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses a
- * CacheResult as the source for the stream. The CacheResult stored mimetype
- * and encoding is added to the HTTP response headers.
- */
-class CacheLoader extends StreamLoader {
-
- CacheManager.CacheResult mCacheResult; // Content source
-
- /**
- * Constructs a CacheLoader for use when loading content from the cache.
- *
- * @param loadListener LoadListener to pass the content to
- * @param result CacheResult used as the source for the content.
- */
- CacheLoader(LoadListener loadListener, CacheManager.CacheResult result) {
- super(loadListener);
-
- assert !JniUtil.useChromiumHttpStack();
-
- mCacheResult = result;
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- mDataStream = mCacheResult.inStream;
- mContentLength = mCacheResult.contentLength;
- mLoadListener.status(1, 1, mCacheResult.httpStatusCode, "OK");
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- StringBuilder sb = new StringBuilder(mCacheResult.mimeType);
- if (!TextUtils.isEmpty(mCacheResult.encoding)) {
- sb.append(';');
- sb.append(mCacheResult.encoding);
- }
- headers.setContentType(sb.toString());
-
- if (!TextUtils.isEmpty(mCacheResult.location)) {
- headers.setLocation(mCacheResult.location);
- }
-
- if (!TextUtils.isEmpty(mCacheResult.expiresString)) {
- headers.setExpires(mCacheResult.expiresString);
- }
-
- if (!TextUtils.isEmpty(mCacheResult.contentdisposition)) {
- headers.setContentDisposition(mCacheResult.contentdisposition);
- }
-
- if (!TextUtils.isEmpty(mCacheResult.crossDomain)) {
- headers.setXPermittedCrossDomainPolicies(mCacheResult.crossDomain);
- }
- }
-}
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 36b4de1..6a85e00 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -57,33 +57,8 @@
static final String HEADER_KEY_IFMODIFIEDSINCE = "if-modified-since";
static final String HEADER_KEY_IFNONEMATCH = "if-none-match";
- private static final String NO_STORE = "no-store";
- private static final String NO_CACHE = "no-cache";
- private static final String MAX_AGE = "max-age";
- private static final String MANIFEST_MIME = "text/cache-manifest";
-
- private static long CACHE_THRESHOLD = 6 * 1024 * 1024;
- private static long CACHE_TRIM_AMOUNT = 2 * 1024 * 1024;
-
- // Limit the maximum cache file size to half of the normal capacity
- static long CACHE_MAX_SIZE = (CACHE_THRESHOLD - CACHE_TRIM_AMOUNT) / 2;
-
- // Reference count the enable/disable transaction
- private static int mRefCount;
-
- // trimCacheIfNeeded() is called when a page is fully loaded. But JavaScript
- // can load the content, e.g. in a slideshow, continuously, so we need to
- // trim the cache on a timer base too. endCacheTransaction() is called on a
- // timer base. We share the same timer with less frequent update.
- private static int mTrimCacheCount = 0;
- private static final int TRIM_CACHE_INTERVAL = 5;
-
- private static WebViewDatabase mDataBase;
private static File mBaseDir;
- // Flag to clear the cache when the CacheManager is initialized
- private static boolean mClearCacheOnInit = false;
-
/**
* Represents a resource stored in the HTTP cache. Instances of this class
* can be obtained by calling
@@ -260,51 +235,12 @@
* @param context The application context
*/
static void init(Context context) {
- if (JniUtil.useChromiumHttpStack()) {
- // This isn't actually where the real cache lives, but where we put files for the
- // purpose of getCacheFile().
- mBaseDir = new File(context.getCacheDir(), "webviewCacheChromiumStaging");
- if (!mBaseDir.exists()) {
- mBaseDir.mkdirs();
- }
- return;
- }
-
- mDataBase = WebViewDatabase.getInstance(context.getApplicationContext());
- mBaseDir = new File(context.getCacheDir(), "webviewCache");
- if (createCacheDirectory() && mClearCacheOnInit) {
- removeAllCacheFiles();
- mClearCacheOnInit = false;
- }
- }
-
- /**
- * Create the cache directory if it does not already exist.
- *
- * @return true if the cache directory didn't exist and was created.
- */
- static private boolean createCacheDirectory() {
- assert !JniUtil.useChromiumHttpStack();
-
+ // This isn't actually where the real cache lives, but where we put files for the
+ // purpose of getCacheFile().
+ mBaseDir = new File(context.getCacheDir(), "webviewCacheChromiumStaging");
if (!mBaseDir.exists()) {
- if(!mBaseDir.mkdirs()) {
- Log.w(LOGTAG, "Unable to create webviewCache directory");
- return false;
- }
- FileUtils.setPermissions(
- mBaseDir.toString(),
- FileUtils.S_IRWXU | FileUtils.S_IRWXG,
- -1, -1);
- // If we did create the directory, we need to flush
- // the cache database. The directory could be recreated
- // because the system flushed all the data/cache directories
- // to free up disk space.
- // delete rows in the cache database
- WebViewWorker.getHandler().sendEmptyMessage(
- WebViewWorker.MSG_CLEAR_CACHE);
- return true;
+ mBaseDir.mkdirs();
}
- return false;
}
/**
@@ -329,51 +265,6 @@
return false;
}
- // only called from WebViewWorkerThread
- // make sure to call enableTransaction/disableTransaction in pair
- static boolean enableTransaction() {
- assert !JniUtil.useChromiumHttpStack();
-
- if (++mRefCount == 1) {
- mDataBase.startCacheTransaction();
- return true;
- }
- return false;
- }
-
- // only called from WebViewWorkerThread
- // make sure to call enableTransaction/disableTransaction in pair
- static boolean disableTransaction() {
- assert !JniUtil.useChromiumHttpStack();
-
- if (--mRefCount == 0) {
- mDataBase.endCacheTransaction();
- return true;
- }
- return false;
- }
-
- // only called from WebViewWorkerThread
- // make sure to call startTransaction/endTransaction in pair
- static boolean startTransaction() {
- assert !JniUtil.useChromiumHttpStack();
-
- return mDataBase.startCacheTransaction();
- }
-
- // only called from WebViewWorkerThread
- // make sure to call startTransaction/endTransaction in pair
- static boolean endTransaction() {
- assert !JniUtil.useChromiumHttpStack();
-
- boolean ret = mDataBase.endCacheTransaction();
- if (++mTrimCacheCount >= TRIM_CACHE_INTERVAL) {
- mTrimCacheCount = 0;
- trimCacheIfNeeded();
- }
- return ret;
- }
-
/**
* Starts a cache transaction. Returns true if this is the only running
* transaction. Otherwise, this transaction is nested inside currently
@@ -415,9 +306,8 @@
return getCacheFile(url, 0, headers);
}
- private static CacheResult getCacheFileChromiumHttpStack(String url) {
- assert JniUtil.useChromiumHttpStack();
-
+ static CacheResult getCacheFile(String url, long postIdentifier,
+ Map<String, String> headers) {
CacheResult result = nativeGetCacheResult(url);
if (result == null) {
return null;
@@ -435,49 +325,6 @@
// system. If it is gone, what should we do?
return null;
}
- return result;
- }
-
- private static CacheResult getCacheFileAndroidHttpStack(String url,
- long postIdentifier) {
- assert !JniUtil.useChromiumHttpStack();
-
- String databaseKey = getDatabaseKey(url, postIdentifier);
- CacheResult result = mDataBase.getCache(databaseKey);
- if (result == null) {
- return null;
- }
- if (result.contentLength == 0) {
- if (!isCachableRedirect(result.httpStatusCode)) {
- // This should not happen. If it does, remove it.
- mDataBase.removeCache(databaseKey);
- return null;
- }
- } else {
- File src = new File(mBaseDir, result.localPath);
- try {
- // Open the file here so that even if it is deleted, the content
- // is still readable by the caller until close() is called.
- result.inStream = new FileInputStream(src);
- } catch (FileNotFoundException e) {
- // The files in the cache directory can be removed by the
- // system. If it is gone, clean up the database.
- mDataBase.removeCache(databaseKey);
- return null;
- }
- }
- return result;
- }
-
- static CacheResult getCacheFile(String url, long postIdentifier,
- Map<String, String> headers) {
- CacheResult result = JniUtil.useChromiumHttpStack() ?
- getCacheFileChromiumHttpStack(url) :
- getCacheFileAndroidHttpStack(url, postIdentifier);
-
- if (result == null) {
- return null;
- }
// A null value for headers is used by CACHE_MODE_CACHE_ONLY to imply
// that we should provide the cache result even if it is expired.
@@ -516,66 +363,8 @@
*/
static CacheResult createCacheFile(String url, int statusCode,
Headers headers, String mimeType, boolean forceCache) {
- if (JniUtil.useChromiumHttpStack()) {
- // This method is public but hidden. We break functionality.
- return null;
- }
-
- return createCacheFile(url, statusCode, headers, mimeType, 0,
- forceCache);
- }
-
- static CacheResult createCacheFile(String url, int statusCode,
- Headers headers, String mimeType, long postIdentifier,
- boolean forceCache) {
- assert !JniUtil.useChromiumHttpStack();
-
- String databaseKey = getDatabaseKey(url, postIdentifier);
-
- // according to the rfc 2616, the 303 response MUST NOT be cached.
- if (statusCode == 303) {
- // remove the saved cache if there is any
- mDataBase.removeCache(databaseKey);
- return null;
- }
-
- // like the other browsers, do not cache redirects containing a cookie
- // header.
- if (isCachableRedirect(statusCode) && !headers.getSetCookie().isEmpty()) {
- // remove the saved cache if there is any
- mDataBase.removeCache(databaseKey);
- return null;
- }
-
- CacheResult ret = parseHeaders(statusCode, headers, mimeType);
- if (ret == null) {
- // this should only happen if the headers has "no-store" in the
- // cache-control. remove the saved cache if there is any
- mDataBase.removeCache(databaseKey);
- } else {
- setupFiles(databaseKey, ret);
- try {
- ret.outStream = new FileOutputStream(ret.outFile);
- } catch (FileNotFoundException e) {
- // This can happen with the system did a purge and our
- // subdirectory has gone, so lets try to create it again
- if (createCacheDirectory()) {
- try {
- ret.outStream = new FileOutputStream(ret.outFile);
- } catch (FileNotFoundException e2) {
- // We failed to create the file again, so there
- // is something else wrong. Return null.
- return null;
- }
- } else {
- // Failed to create cache directory
- return null;
- }
- }
- ret.mimeType = mimeType;
- }
-
- return ret;
+ // This method is public but hidden. We break functionality.
+ return null;
}
/**
@@ -598,64 +387,24 @@
return;
}
- if (JniUtil.useChromiumHttpStack()) {
- // This method is exposed in the public API but the API provides no
- // way to obtain a new CacheResult object with a non-null output
- // stream ...
- // - CacheResult objects returned by getCacheFile() have a null
- // output stream.
- // - new CacheResult objects have a null output stream and no
- // setter is provided.
- // Since this method throws a null pointer exception in this case,
- // it is effectively useless from the point of view of the public
- // API.
- //
- // With the Chromium HTTP stack we continue to throw the same
- // exception for 'backwards compatibility' with the Android HTTP
- // stack.
- //
- // This method is not used from within this package with the
- // Chromium HTTP stack, and for public API use, we should already
- // have thrown an exception above.
- assert false;
- return;
- }
-
- if (!cacheRet.outFile.exists()) {
- // the file in the cache directory can be removed by the system
- return;
- }
-
- boolean redirect = isCachableRedirect(cacheRet.httpStatusCode);
- if (redirect) {
- // location is in database, no need to keep the file
- cacheRet.contentLength = 0;
- cacheRet.localPath = "";
- }
- if ((redirect || cacheRet.contentLength == 0)
- && !cacheRet.outFile.delete()) {
- Log.e(LOGTAG, cacheRet.outFile.getPath() + " delete failed.");
- }
- if (cacheRet.contentLength == 0) {
- return;
- }
-
- mDataBase.addCache(getDatabaseKey(url, postIdentifier), cacheRet);
-
- if (DebugFlags.CACHE_MANAGER) {
- Log.v(LOGTAG, "saveCacheFile for url " + url);
- }
- }
-
- static boolean cleanupCacheFile(CacheResult cacheRet) {
- assert !JniUtil.useChromiumHttpStack();
-
- try {
- cacheRet.outStream.close();
- } catch (IOException e) {
- return false;
- }
- return cacheRet.outFile.delete();
+ // This method is exposed in the public API but the API provides no
+ // way to obtain a new CacheResult object with a non-null output
+ // stream ...
+ // - CacheResult objects returned by getCacheFile() have a null
+ // output stream.
+ // - new CacheResult objects have a null output stream and no
+ // setter is provided.
+ // Since this method throws a null pointer exception in this case,
+ // it is effectively useless from the point of view of the public
+ // API.
+ //
+ // With the Chromium HTTP stack we continue to throw the same
+ // exception for 'backwards compatibility' with the Android HTTP
+ // stack.
+ //
+ // This method is not used from within this package, and for public API
+ // use, we should already have thrown an exception above.
+ assert false;
}
/**
@@ -664,21 +413,6 @@
* @return Whether the removal succeeded.
*/
static boolean removeAllCacheFiles() {
- // Note, this is called before init() when the database is
- // created or upgraded.
- if (mBaseDir == null) {
- // This method should not be called before init() when using the
- // chrome http stack
- assert !JniUtil.useChromiumHttpStack();
- // Init() has not been called yet, so just flag that
- // we need to clear the cache when init() is called.
- mClearCacheOnInit = true;
- return true;
- }
- // delete rows in the cache database
- if (!JniUtil.useChromiumHttpStack())
- WebViewWorker.getHandler().sendEmptyMessage(WebViewWorker.MSG_CLEAR_CACHE);
-
// delete cache files in a separate thread to not block UI.
final Runnable clearCache = new Runnable() {
public void run() {
@@ -703,323 +437,5 @@
return true;
}
- static void trimCacheIfNeeded() {
- assert !JniUtil.useChromiumHttpStack();
-
- if (mDataBase.getCacheTotalSize() > CACHE_THRESHOLD) {
- List<String> pathList = mDataBase.trimCache(CACHE_TRIM_AMOUNT);
- int size = pathList.size();
- for (int i = 0; i < size; i++) {
- File f = new File(mBaseDir, pathList.get(i));
- if (!f.delete()) {
- Log.e(LOGTAG, f.getPath() + " delete failed.");
- }
- }
- // remove the unreferenced files in the cache directory
- final List<String> fileList = mDataBase.getAllCacheFileNames();
- if (fileList == null) return;
- String[] toDelete = mBaseDir.list(new FilenameFilter() {
- public boolean accept(File dir, String filename) {
- if (fileList.contains(filename)) {
- return false;
- } else {
- return true;
- }
- }
- });
- if (toDelete == null) return;
- size = toDelete.length;
- for (int i = 0; i < size; i++) {
- File f = new File(mBaseDir, toDelete[i]);
- if (!f.delete()) {
- Log.e(LOGTAG, f.getPath() + " delete failed.");
- }
- }
- }
- }
-
- static void clearCache() {
- assert !JniUtil.useChromiumHttpStack();
-
- // delete database
- mDataBase.clearCache();
- }
-
- private static boolean isCachableRedirect(int statusCode) {
- if (statusCode == 301 || statusCode == 302 || statusCode == 307) {
- // as 303 can't be cached, we do not return true
- return true;
- } else {
- return false;
- }
- }
-
- private static String getDatabaseKey(String url, long postIdentifier) {
- assert !JniUtil.useChromiumHttpStack();
-
- if (postIdentifier == 0) return url;
- return postIdentifier + url;
- }
-
- @SuppressWarnings("deprecation")
- private static void setupFiles(String url, CacheResult cacheRet) {
- assert !JniUtil.useChromiumHttpStack();
-
- if (true) {
- // Note: SHA1 is much stronger hash. But the cost of setupFiles() is
- // 3.2% cpu time for a fresh load of nytimes.com. While a simple
- // String.hashCode() is only 0.6%. If adding the collision resolving
- // to String.hashCode(), it makes the cpu time to be 1.6% for a
- // fresh load, but 5.3% for the worst case where all the files
- // already exist in the file system, but database is gone. So it
- // needs to resolve collision for every file at least once.
- int hashCode = url.hashCode();
- StringBuffer ret = new StringBuffer(8);
- appendAsHex(hashCode, ret);
- String path = ret.toString();
- File file = new File(mBaseDir, path);
- if (true) {
- boolean checkOldPath = true;
- // Check hash collision. If the hash file doesn't exist, just
- // continue. There is a chance that the old cache file is not
- // same as the hash file. As mDataBase.getCache() is more
- // expansive than "leak" a file until clear cache, don't bother.
- // If the hash file exists, make sure that it is same as the
- // cache file. If it is not, resolve the collision.
- while (file.exists()) {
- if (checkOldPath) {
- CacheResult oldResult = mDataBase.getCache(url);
- if (oldResult != null && oldResult.contentLength > 0) {
- if (path.equals(oldResult.localPath)) {
- path = oldResult.localPath;
- } else {
- path = oldResult.localPath;
- file = new File(mBaseDir, path);
- }
- break;
- }
- checkOldPath = false;
- }
- ret = new StringBuffer(8);
- appendAsHex(++hashCode, ret);
- path = ret.toString();
- file = new File(mBaseDir, path);
- }
- }
- cacheRet.localPath = path;
- cacheRet.outFile = file;
- } else {
- // get hash in byte[]
- Digest digest = new SHA1Digest();
- int digestLen = digest.getDigestSize();
- byte[] hash = new byte[digestLen];
- int urlLen = url.length();
- byte[] data = new byte[urlLen];
- url.getBytes(0, urlLen, data, 0);
- digest.update(data, 0, urlLen);
- digest.doFinal(hash, 0);
- // convert byte[] to hex String
- StringBuffer result = new StringBuffer(2 * digestLen);
- for (int i = 0; i < digestLen; i = i + 4) {
- int h = (0x00ff & hash[i]) << 24 | (0x00ff & hash[i + 1]) << 16
- | (0x00ff & hash[i + 2]) << 8 | (0x00ff & hash[i + 3]);
- appendAsHex(h, result);
- }
- cacheRet.localPath = result.toString();
- cacheRet.outFile = new File(mBaseDir, cacheRet.localPath);
- }
- }
-
- private static void appendAsHex(int i, StringBuffer ret) {
- assert !JniUtil.useChromiumHttpStack();
-
- String hex = Integer.toHexString(i);
- switch (hex.length()) {
- case 1:
- ret.append("0000000");
- break;
- case 2:
- ret.append("000000");
- break;
- case 3:
- ret.append("00000");
- break;
- case 4:
- ret.append("0000");
- break;
- case 5:
- ret.append("000");
- break;
- case 6:
- ret.append("00");
- break;
- case 7:
- ret.append("0");
- break;
- }
- ret.append(hex);
- }
-
- private static CacheResult parseHeaders(int statusCode, Headers headers,
- String mimeType) {
- assert !JniUtil.useChromiumHttpStack();
-
- // if the contentLength is already larger than CACHE_MAX_SIZE, skip it
- if (headers.getContentLength() > CACHE_MAX_SIZE) return null;
-
- // The HTML 5 spec, section 6.9.4, step 7.3 of the application cache
- // process states that HTTP caching rules are ignored for the
- // purposes of the application cache download process.
- // At this point we can't tell that if a file is part of this process,
- // except for the manifest, which has its own mimeType.
- // TODO: work out a way to distinguish all responses that are part of
- // the application download process and skip them.
- if (MANIFEST_MIME.equals(mimeType)) return null;
-
- // TODO: if authenticated or secure, return null
- CacheResult ret = new CacheResult();
- ret.httpStatusCode = statusCode;
-
- ret.location = headers.getLocation();
-
- ret.expires = -1;
- ret.expiresString = headers.getExpires();
- if (ret.expiresString != null) {
- try {
- ret.expires = AndroidHttpClient.parseDate(ret.expiresString);
- } catch (IllegalArgumentException ex) {
- // Take care of the special "-1" and "0" cases
- if ("-1".equals(ret.expiresString)
- || "0".equals(ret.expiresString)) {
- // make it expired, but can be used for history navigation
- ret.expires = 0;
- } else {
- Log.e(LOGTAG, "illegal expires: " + ret.expiresString);
- }
- }
- }
-
- ret.contentdisposition = headers.getContentDisposition();
-
- ret.crossDomain = headers.getXPermittedCrossDomainPolicies();
-
- // lastModified and etag may be set back to http header. So they can't
- // be empty string.
- String lastModified = headers.getLastModified();
- if (lastModified != null && lastModified.length() > 0) {
- ret.lastModified = lastModified;
- }
-
- String etag = headers.getEtag();
- if (etag != null && etag.length() > 0) {
- ret.etag = etag;
- }
-
- String cacheControl = headers.getCacheControl();
- if (cacheControl != null) {
- String[] controls = cacheControl.toLowerCase().split("[ ,;]");
- boolean noCache = false;
- for (int i = 0; i < controls.length; i++) {
- if (NO_STORE.equals(controls[i])) {
- return null;
- }
- // According to the spec, 'no-cache' means that the content
- // must be re-validated on every load. It does not mean that
- // the content can not be cached. set to expire 0 means it
- // can only be used in CACHE_MODE_CACHE_ONLY case
- if (NO_CACHE.equals(controls[i])) {
- ret.expires = 0;
- noCache = true;
- // if cache control = no-cache has been received, ignore max-age
- // header, according to http spec:
- // If a request includes the no-cache directive, it SHOULD NOT
- // include min-fresh, max-stale, or max-age.
- } else if (controls[i].startsWith(MAX_AGE) && !noCache) {
- int separator = controls[i].indexOf('=');
- if (separator < 0) {
- separator = controls[i].indexOf(':');
- }
- if (separator > 0) {
- String s = controls[i].substring(separator + 1);
- try {
- long sec = Long.parseLong(s);
- if (sec >= 0) {
- ret.expires = System.currentTimeMillis() + 1000
- * sec;
- }
- } catch (NumberFormatException ex) {
- if ("1d".equals(s)) {
- // Take care of the special "1d" case
- ret.expires = System.currentTimeMillis() + 86400000; // 24*60*60*1000
- } else {
- Log.e(LOGTAG, "exception in parseHeaders for "
- + "max-age:"
- + controls[i].substring(separator + 1));
- ret.expires = 0;
- }
- }
- }
- }
- }
- }
-
- // According to RFC 2616 section 14.32:
- // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the
- // client had sent "Cache-Control: no-cache"
- if (NO_CACHE.equals(headers.getPragma())) {
- ret.expires = 0;
- }
-
- // According to RFC 2616 section 13.2.4, if an expiration has not been
- // explicitly defined a heuristic to set an expiration may be used.
- if (ret.expires == -1) {
- if (ret.httpStatusCode == 301) {
- // If it is a permanent redirect, and it did not have an
- // explicit cache directive, then it never expires
- ret.expires = Long.MAX_VALUE;
- } else if (ret.httpStatusCode == 302 || ret.httpStatusCode == 307) {
- // If it is temporary redirect, expires
- ret.expires = 0;
- } else if (ret.lastModified == null) {
- // When we have no last-modified, then expire the content with
- // in 24hrs as, according to the RFC, longer time requires a
- // warning 113 to be added to the response.
-
- // Only add the default expiration for non-html markup. Some
- // sites like news.google.com have no cache directives.
- if (!mimeType.startsWith("text/html")) {
- ret.expires = System.currentTimeMillis() + 86400000; // 24*60*60*1000
- } else {
- // Setting a expires as zero will cache the result for
- // forward/back nav.
- ret.expires = 0;
- }
- } else {
- // If we have a last-modified value, we could use it to set the
- // expiration. Suggestion from RFC is 10% of time since
- // last-modified. As we are on mobile, loads are expensive,
- // increasing this to 20%.
-
- // 24 * 60 * 60 * 1000
- long lastmod = System.currentTimeMillis() + 86400000;
- try {
- lastmod = AndroidHttpClient.parseDate(ret.lastModified);
- } catch (IllegalArgumentException ex) {
- Log.e(LOGTAG, "illegal lastModified: " + ret.lastModified);
- }
- long difference = System.currentTimeMillis() - lastmod;
- if (difference > 0) {
- ret.expires = System.currentTimeMillis() + difference / 5;
- } else {
- // last modified is in the future, expire the content
- // on the last modified
- ret.expires = lastmod;
- }
- }
- }
-
- return ret;
- }
-
private static native CacheResult nativeGetCacheResult(String url);
}
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 95d9275..3a05bca 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -920,10 +920,6 @@
if (PERF_PROBE) {
mWebCoreThreadTime = SystemClock.currentThreadTimeMillis();
mWebCoreIdleTime = 0;
- if (!JniUtil.useChromiumHttpStack()) {
- // Network is only used with the Android HTTP stack.
- Network.getInstance(mContext).startTiming();
- }
// un-comment this if PERF_PROBE is true
// Looper.myQueue().setWaitCallback(mIdleCallback);
}
@@ -941,10 +937,6 @@
Log.d("WebCore", "WebCore thread used " +
(SystemClock.currentThreadTimeMillis() - mWebCoreThreadTime)
+ " ms and idled " + mWebCoreIdleTime + " ms");
- if (!JniUtil.useChromiumHttpStack()) {
- // Network is only used with the Android HTTP stack.
- Network.getInstance(mContext).stopTiming();
- }
}
Message msg = obtainMessage(PAGE_FINISHED, url);
sendMessage(msg);
diff --git a/core/java/android/webkit/ContentLoader.java b/core/java/android/webkit/ContentLoader.java
deleted file mode 100644
index d13210a..0000000
--- a/core/java/android/webkit/ContentLoader.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.net.Uri;
-
-/**
- * This class is a concrete implementation of StreamLoader that loads
- * "content:" URIs
- */
-class ContentLoader extends StreamLoader {
-
- private String mUrl;
- private String mContentType;
-
- /**
- * Construct a ContentLoader with the specified content URI
- *
- * @param rawUrl "content:" url pointing to content to be loaded. This url
- * is the same url passed in to the WebView.
- * @param loadListener LoadListener to pass the content to
- */
- ContentLoader(String rawUrl, LoadListener loadListener) {
- super(loadListener);
-
- /* strip off mimetype */
- int mimeIndex = rawUrl.lastIndexOf('?');
- if (mimeIndex != -1) {
- mUrl = rawUrl.substring(0, mimeIndex);
- mContentType = rawUrl.substring(mimeIndex + 1);
- } else {
- mUrl = rawUrl;
- }
-
- }
-
- private String errString(Exception ex) {
- String exMessage = ex.getMessage();
- String errString = mContext.getString(
- com.android.internal.R.string.httpErrorFileNotFound);
- if (exMessage != null) {
- errString += " " + exMessage;
- }
- return errString;
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- Uri uri = Uri.parse(mUrl);
- if (uri == null) {
- mLoadListener.error(
- EventHandler.FILE_NOT_FOUND_ERROR,
- mContext.getString(
- com.android.internal.R.string.httpErrorBadUrl) +
- " " + mUrl);
- return false;
- }
-
- try {
- mDataStream = mContext.getContentResolver().openInputStream(uri);
- mLoadListener.status(1, 1, 200, "OK");
- } catch (java.io.FileNotFoundException ex) {
- mLoadListener.error(EventHandler.FILE_NOT_FOUND_ERROR, errString(ex));
- return false;
- } catch (RuntimeException ex) {
- // readExceptionWithFileNotFoundExceptionFromParcel in DatabaseUtils
- // can throw a serial of RuntimeException. Catch them all here.
- mLoadListener.error(EventHandler.FILE_ERROR, errString(ex));
- return false;
- }
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- if (mContentType != null) {
- headers.setContentType("text/html");
- }
- // content can change, we don't want WebKit to cache it
- headers.setCacheControl("no-store, no-cache");
- }
-}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index c500a76..497cab7 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -95,11 +95,6 @@
// max domain count to limit RAM cookie takes less than 100k,
private static final int MAX_RAM_DOMAIN_COUNT = 15;
- private Map<String, ArrayList<Cookie>> mCookieMap = new LinkedHashMap
- <String, ArrayList<Cookie>>(MAX_DOMAIN_COUNT, 0.75f, true);
-
- private boolean mAcceptCookie = true;
-
private int mPendingCookieOperations = 0;
/**
@@ -268,12 +263,7 @@
* cookies
*/
public synchronized void setAcceptCookie(boolean accept) {
- if (JniUtil.useChromiumHttpStack()) {
- nativeSetAcceptCookie(accept);
- return;
- }
-
- mAcceptCookie = accept;
+ nativeSetAcceptCookie(accept);
}
/**
@@ -282,11 +272,7 @@
* @return True if {@link WebView} instances send and accept cookies
*/
public synchronized boolean acceptCookie() {
- if (JniUtil.useChromiumHttpStack()) {
- return nativeAcceptCookie();
- }
-
- return mAcceptCookie;
+ return nativeAcceptCookie();
}
/**
@@ -299,20 +285,7 @@
* 'Set-Cookie' HTTP response header
*/
public void setCookie(String url, String value) {
- if (JniUtil.useChromiumHttpStack()) {
- setCookie(url, value, false);
- return;
- }
-
- WebAddress uri;
- try {
- uri = new WebAddress(url);
- } catch (ParseException ex) {
- Log.e(LOGTAG, "Bad address: " + url);
- return;
- }
-
- setCookie(uri, value);
+ setCookie(url, value, false);
}
/**
@@ -323,11 +296,6 @@
* @param privateBrowsing Whether to use the private browsing cookie jar
*/
void setCookie(String url, String value, boolean privateBrowsing) {
- if (!JniUtil.useChromiumHttpStack()) {
- setCookie(url, value);
- return;
- }
-
WebAddress uri;
try {
uri = new WebAddress(url);
@@ -340,136 +308,13 @@
}
/**
- * See {@link setCookie(String, String)}
- * @param uri The WebAddress for which the cookie is set
- * @param value The value of the cookie, as a string, using the format of
- * the 'Set-Cookie' HTTP response header
- */
- synchronized void setCookie(WebAddress uri, String value) {
- if (JniUtil.useChromiumHttpStack()) {
- nativeSetCookie(uri.toString(), value, false);
- return;
- }
-
- if (value != null && value.length() > MAX_COOKIE_LENGTH) {
- return;
- }
- if (!mAcceptCookie || uri == null) {
- return;
- }
- if (DebugFlags.COOKIE_MANAGER) {
- Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value);
- }
-
- String[] hostAndPath = getHostAndPath(uri);
- if (hostAndPath == null) {
- return;
- }
-
- // For default path, when setting a cookie, the spec says:
- //Path: Defaults to the path of the request URL that generated the
- // Set-Cookie response, up to, but not including, the
- // right-most /.
- if (hostAndPath[1].length() > 1) {
- int index = hostAndPath[1].lastIndexOf(PATH_DELIM);
- hostAndPath[1] = hostAndPath[1].substring(0,
- index > 0 ? index : index + 1);
- }
-
- ArrayList<Cookie> cookies = null;
- try {
- cookies = parseCookie(hostAndPath[0], hostAndPath[1], value);
- } catch (RuntimeException ex) {
- Log.e(LOGTAG, "parse cookie failed for: " + value);
- }
-
- if (cookies == null || cookies.size() == 0) {
- return;
- }
-
- String baseDomain = getBaseDomain(hostAndPath[0]);
- ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain);
- if (cookieList == null) {
- cookieList = CookieSyncManager.getInstance()
- .getCookiesForDomain(baseDomain);
- mCookieMap.put(baseDomain, cookieList);
- }
-
- long now = System.currentTimeMillis();
- int size = cookies.size();
- for (int i = 0; i < size; i++) {
- Cookie cookie = cookies.get(i);
-
- boolean done = false;
- Iterator<Cookie> iter = cookieList.iterator();
- while (iter.hasNext()) {
- Cookie cookieEntry = iter.next();
- if (cookie.exactMatch(cookieEntry)) {
- // expires == -1 means no expires defined. Otherwise
- // negative means far future
- if (cookie.expires < 0 || cookie.expires > now) {
- // secure cookies can't be overwritten by non-HTTPS url
- if (!cookieEntry.secure || HTTPS.equals(uri.getScheme())) {
- cookieEntry.value = cookie.value;
- cookieEntry.expires = cookie.expires;
- cookieEntry.secure = cookie.secure;
- cookieEntry.lastAcessTime = now;
- cookieEntry.lastUpdateTime = now;
- cookieEntry.mode = Cookie.MODE_REPLACED;
- }
- } else {
- cookieEntry.lastUpdateTime = now;
- cookieEntry.mode = Cookie.MODE_DELETED;
- }
- done = true;
- break;
- }
- }
-
- // expires == -1 means no expires defined. Otherwise negative means
- // far future
- if (!done && (cookie.expires < 0 || cookie.expires > now)) {
- cookie.lastAcessTime = now;
- cookie.lastUpdateTime = now;
- cookie.mode = Cookie.MODE_NEW;
- if (cookieList.size() > MAX_COOKIE_COUNT_PER_BASE_DOMAIN) {
- Cookie toDelete = new Cookie();
- toDelete.lastAcessTime = now;
- Iterator<Cookie> iter2 = cookieList.iterator();
- while (iter2.hasNext()) {
- Cookie cookieEntry2 = iter2.next();
- if ((cookieEntry2.lastAcessTime < toDelete.lastAcessTime)
- && cookieEntry2.mode != Cookie.MODE_DELETED) {
- toDelete = cookieEntry2;
- }
- }
- toDelete.mode = Cookie.MODE_DELETED;
- }
- cookieList.add(cookie);
- }
- }
- }
-
- /**
* Gets the cookies for the given URL.
* @param url The URL for which the cookies are requested
* @return value The cookies as a string, using the format of the 'Cookie'
* HTTP request header
*/
public String getCookie(String url) {
- if (JniUtil.useChromiumHttpStack()) {
- return getCookie(url, false);
- }
-
- WebAddress uri;
- try {
- uri = new WebAddress(url);
- } catch (ParseException ex) {
- Log.e(LOGTAG, "Bad address: " + url);
- return null;
- }
-
- return getCookie(uri);
+ return getCookie(url, false);
}
/**
@@ -481,11 +326,6 @@
* @hide Used by Browser, no intention to publish.
*/
public String getCookie(String url, boolean privateBrowsing) {
- if (!JniUtil.useChromiumHttpStack()) {
- // Just redirect to regular get cookie for android stack
- return getCookie(url);
- }
-
WebAddress uri;
try {
uri = new WebAddress(url);
@@ -506,76 +346,7 @@
* @hide Used by RequestHandle, no intention to publish.
*/
public synchronized String getCookie(WebAddress uri) {
- if (JniUtil.useChromiumHttpStack()) {
- return nativeGetCookie(uri.toString(), false);
- }
-
- if (!mAcceptCookie || uri == null) {
- return null;
- }
-
- String[] hostAndPath = getHostAndPath(uri);
- if (hostAndPath == null) {
- return null;
- }
-
- String baseDomain = getBaseDomain(hostAndPath[0]);
- ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain);
- if (cookieList == null) {
- cookieList = CookieSyncManager.getInstance()
- .getCookiesForDomain(baseDomain);
- mCookieMap.put(baseDomain, cookieList);
- }
-
- long now = System.currentTimeMillis();
- boolean secure = HTTPS.equals(uri.getScheme());
- Iterator<Cookie> iter = cookieList.iterator();
-
- SortedSet<Cookie> cookieSet = new TreeSet<Cookie>(COMPARATOR);
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.domainMatch(hostAndPath[0]) &&
- cookie.pathMatch(hostAndPath[1])
- // expires == -1 means no expires defined. Otherwise
- // negative means far future
- && (cookie.expires < 0 || cookie.expires > now)
- && (!cookie.secure || secure)
- && cookie.mode != Cookie.MODE_DELETED) {
- cookie.lastAcessTime = now;
- cookieSet.add(cookie);
- }
- }
-
- StringBuilder ret = new StringBuilder(256);
- Iterator<Cookie> setIter = cookieSet.iterator();
- while (setIter.hasNext()) {
- Cookie cookie = setIter.next();
- if (ret.length() > 0) {
- ret.append(SEMICOLON);
- // according to RC2109, SEMICOLON is official separator,
- // but when log in yahoo.com, it needs WHITE_SPACE too.
- ret.append(WHITE_SPACE);
- }
-
- ret.append(cookie.name);
- if (cookie.value != null) {
- ret.append(EQUAL);
- ret.append(cookie.value);
- }
- }
-
- if (ret.length() > 0) {
- if (DebugFlags.COOKIE_MANAGER) {
- Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret);
- }
- return ret.toString();
- } else {
- if (DebugFlags.COOKIE_MANAGER) {
- Log.v(LOGTAG, "getCookie: uri: " + uri
- + " But can't find cookie.");
- }
- return null;
- }
+ return nativeGetCookie(uri.toString(), false);
}
/**
@@ -609,59 +380,20 @@
*/
public void removeSessionCookie() {
signalCookieOperationsStart();
- if (JniUtil.useChromiumHttpStack()) {
- new AsyncTask<Void, Void, Void>() {
- protected Void doInBackground(Void... none) {
- nativeRemoveSessionCookie();
- signalCookieOperationsComplete();
- return null;
- }
- }.execute();
- return;
- }
-
- final Runnable clearCache = new Runnable() {
- public void run() {
- synchronized(CookieManager.this) {
- Collection<ArrayList<Cookie>> cookieList = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
- while (listIter.hasNext()) {
- ArrayList<Cookie> list = listIter.next();
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.expires == -1) {
- iter.remove();
- }
- }
- }
- CookieSyncManager.getInstance().clearSessionCookies();
- signalCookieOperationsComplete();
- }
+ new AsyncTask<Void, Void, Void>() {
+ protected Void doInBackground(Void... none) {
+ nativeRemoveSessionCookie();
+ signalCookieOperationsComplete();
+ return null;
}
- };
- new Thread(clearCache).start();
+ }.execute();
}
/**
* Removes all cookies.
*/
public void removeAllCookie() {
- if (JniUtil.useChromiumHttpStack()) {
- nativeRemoveAllCookie();
- return;
- }
-
- final Runnable clearCache = new Runnable() {
- public void run() {
- synchronized(CookieManager.this) {
- mCookieMap = new LinkedHashMap<String, ArrayList<Cookie>>(
- MAX_DOMAIN_COUNT, 0.75f, true);
- CookieSyncManager.getInstance().clearAllCookies();
- }
- }
- };
- new Thread(clearCache).start();
+ nativeRemoveAllCookie();
}
/**
@@ -669,11 +401,7 @@
* @return True if there are stored cookies.
*/
public synchronized boolean hasCookies() {
- if (JniUtil.useChromiumHttpStack()) {
- return hasCookies(false);
- }
-
- return CookieSyncManager.getInstance().hasCookies();
+ return hasCookies(false);
}
/**
@@ -682,10 +410,6 @@
* @hide Used by Browser, no intention to publish.
*/
public synchronized boolean hasCookies(boolean privateBrowsing) {
- if (!JniUtil.useChromiumHttpStack()) {
- return hasCookies();
- }
-
return nativeHasCookies(privateBrowsing);
}
@@ -693,34 +417,7 @@
* Removes all expired cookies.
*/
public void removeExpiredCookie() {
- if (JniUtil.useChromiumHttpStack()) {
- nativeRemoveExpiredCookie();
- return;
- }
-
- final Runnable clearCache = new Runnable() {
- public void run() {
- synchronized(CookieManager.this) {
- long now = System.currentTimeMillis();
- Collection<ArrayList<Cookie>> cookieList = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
- while (listIter.hasNext()) {
- ArrayList<Cookie> list = listIter.next();
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- // expires == -1 means no expires defined. Otherwise
- // negative means far future
- if (cookie.expires > 0 && cookie.expires < now) {
- iter.remove();
- }
- }
- }
- CookieSyncManager.getInstance().clearExpiredCookies(now);
- }
- }
- };
- new Thread(clearCache).start();
+ nativeRemoveExpiredCookie();
}
/**
@@ -729,9 +426,7 @@
* Flush all cookies managed by the Chrome HTTP stack to flash.
*/
void flushCookieStore() {
- if (JniUtil.useChromiumHttpStack()) {
- nativeFlushCookieStore();
- }
+ nativeFlushCookieStore();
}
/**
@@ -741,11 +436,7 @@
* file scheme URLs
*/
public static boolean allowFileSchemeCookies() {
- if (JniUtil.useChromiumHttpStack()) {
- return nativeAcceptFileSchemeCookies();
- } else {
- return true;
- }
+ return nativeAcceptFileSchemeCookies();
}
/**
@@ -759,457 +450,7 @@
* {@link WebView} or CookieManager instance has been created.
*/
public static void setAcceptFileSchemeCookies(boolean accept) {
- if (JniUtil.useChromiumHttpStack()) {
- nativeSetAcceptFileSchemeCookies(accept);
- }
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Get a list of cookies which are updated since a given time.
- * @param last The given time in millisec
- * @return A list of cookies
- */
- synchronized ArrayList<Cookie> getUpdatedCookiesSince(long last) {
- ArrayList<Cookie> cookies = new ArrayList<Cookie>();
- Collection<ArrayList<Cookie>> cookieList = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
- while (listIter.hasNext()) {
- ArrayList<Cookie> list = listIter.next();
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.lastUpdateTime > last) {
- cookies.add(cookie);
- }
- }
- }
- return cookies;
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Delete a Cookie in the RAM
- * @param cookie Cookie to be deleted
- */
- synchronized void deleteACookie(Cookie cookie) {
- if (cookie.mode == Cookie.MODE_DELETED) {
- String baseDomain = getBaseDomain(cookie.domain);
- ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain);
- if (cookieList != null) {
- cookieList.remove(cookie);
- if (cookieList.isEmpty()) {
- mCookieMap.remove(baseDomain);
- }
- }
- }
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Called after a cookie is synced to FLASH
- * @param cookie Cookie to be synced
- */
- synchronized void syncedACookie(Cookie cookie) {
- cookie.mode = Cookie.MODE_NORMAL;
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Delete the least recent used domains if the total cookie count in RAM
- * exceeds the limit
- * @return A list of cookies which are removed from RAM
- */
- synchronized ArrayList<Cookie> deleteLRUDomain() {
- int count = 0;
- int byteCount = 0;
- int mapSize = mCookieMap.size();
-
- if (mapSize < MAX_RAM_DOMAIN_COUNT) {
- Collection<ArrayList<Cookie>> cookieLists = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator();
- while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
- ArrayList<Cookie> list = listIter.next();
- if (DebugFlags.COOKIE_MANAGER) {
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
- Cookie cookie = iter.next();
- // 14 is 3 * sizeof(long) + sizeof(boolean)
- // + sizeof(byte)
- byteCount += cookie.domain.length()
- + cookie.path.length()
- + cookie.name.length()
- + (cookie.value != null
- ? cookie.value.length()
- : 0)
- + 14;
- count++;
- }
- } else {
- count += list.size();
- }
- }
- }
-
- ArrayList<Cookie> retlist = new ArrayList<Cookie>();
- if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) {
- if (DebugFlags.COOKIE_MANAGER) {
- Log.v(LOGTAG, count + " cookies used " + byteCount
- + " bytes with " + mapSize + " domains");
- }
- Object[] domains = mCookieMap.keySet().toArray();
- int toGo = mapSize / 10 + 1;
- while (toGo-- > 0){
- String domain = domains[toGo].toString();
- if (DebugFlags.COOKIE_MANAGER) {
- Log.v(LOGTAG, "delete domain: " + domain
- + " from RAM cache");
- }
- retlist.addAll(mCookieMap.get(domain));
- mCookieMap.remove(domain);
- }
- }
- return retlist;
- }
-
- /**
- * Extract the host and path out of a uri
- * @param uri The given WebAddress
- * @return The host and path in the format of String[], String[0] is host
- * which has at least two periods, String[1] is path which always
- * ended with "/"
- */
- private String[] getHostAndPath(WebAddress uri) {
- if (uri.getHost() != null && uri.getPath() != null) {
-
- /*
- * The domain (i.e. host) portion of the cookie is supposed to be
- * case-insensitive. We will consistently return the domain in lower
- * case, which allows us to do the more efficient equals comparison
- * instead of equalIgnoreCase.
- *
- * See: http://www.ieft.org/rfc/rfc2965.txt (Section 3.3.3)
- */
- String[] ret = new String[2];
- ret[0] = uri.getHost().toLowerCase();
- ret[1] = uri.getPath();
-
- int index = ret[0].indexOf(PERIOD);
- if (index == -1) {
- if (uri.getScheme().equalsIgnoreCase("file")) {
- // There is a potential bug where a local file path matches
- // another file in the local web server directory. Still
- // "localhost" is the best pseudo domain name.
- ret[0] = "localhost";
- }
- } else if (index == ret[0].lastIndexOf(PERIOD)) {
- // cookie host must have at least two periods
- ret[0] = PERIOD + ret[0];
- }
-
- if (ret[1].charAt(0) != PATH_DELIM) {
- return null;
- }
-
- /*
- * find cookie path, e.g. for http://www.google.com, the path is "/"
- * for http://www.google.com/lab/, the path is "/lab"
- * for http://www.google.com/lab/foo, the path is "/lab/foo"
- * for http://www.google.com/lab?hl=en, the path is "/lab"
- * for http://www.google.com/lab.asp?hl=en, the path is "/lab.asp"
- * Note: the path from URI has at least one "/"
- * See:
- * http://www.unix.com.ua/rfc/rfc2109.html
- */
- index = ret[1].indexOf(QUESTION_MARK);
- if (index != -1) {
- ret[1] = ret[1].substring(0, index);
- }
-
- return ret;
- } else
- return null;
- }
-
- /**
- * Get the base domain for a give host. E.g. mail.google.com will return
- * google.com
- * @param host The give host
- * @return the base domain
- */
- private String getBaseDomain(String host) {
- int startIndex = 0;
- int nextIndex = host.indexOf(PERIOD);
- int lastIndex = host.lastIndexOf(PERIOD);
- while (nextIndex < lastIndex) {
- startIndex = nextIndex + 1;
- nextIndex = host.indexOf(PERIOD, startIndex);
- }
- if (startIndex > 0) {
- return host.substring(startIndex);
- } else {
- return host;
- }
- }
-
- /**
- * parseCookie() parses the cookieString which is a comma-separated list of
- * one or more cookies in the format of "NAME=VALUE; expires=DATE;
- * path=PATH; domain=DOMAIN_NAME; secure httponly" to a list of Cookies.
- * Here is a sample: IGDND=1, IGPC=ET=UB8TSNwtDmQ:AF=0; expires=Sun,
- * 17-Jan-2038 19:14:07 GMT; path=/ig; domain=.google.com, =,
- * PREF=ID=408909b1b304593d:TM=1156459854:LM=1156459854:S=V-vCAU6Sh-gobCfO;
- * expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com which
- * contains 3 cookies IGDND, IGPC, PREF and an empty cookie
- * @param host The default host
- * @param path The default path
- * @param cookieString The string coming from "Set-Cookie:"
- * @return A list of Cookies
- */
- private ArrayList<Cookie> parseCookie(String host, String path,
- String cookieString) {
- ArrayList<Cookie> ret = new ArrayList<Cookie>();
-
- int index = 0;
- int length = cookieString.length();
- while (true) {
- Cookie cookie = null;
-
- // done
- if (index < 0 || index >= length) {
- break;
- }
-
- // skip white space
- if (cookieString.charAt(index) == WHITE_SPACE) {
- index++;
- continue;
- }
-
- /*
- * get NAME=VALUE; pair. detecting the end of a pair is tricky, it
- * can be the end of a string, like "foo=bluh", it can be semicolon
- * like "foo=bluh;path=/"; or it can be enclosed by \", like
- * "foo=\"bluh bluh\";path=/"
- *
- * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret
- * it as one cookie instead of two cookies.
- */
- int semicolonIndex = cookieString.indexOf(SEMICOLON, index);
- int equalIndex = cookieString.indexOf(EQUAL, index);
- cookie = new Cookie(host, path);
-
- // Cookies like "testcookie; path=/;" are valid and used
- // (lovefilm.se).
- // Look for 2 cases:
- // 1. "foo" or "foo;" where equalIndex is -1
- // 2. "foo; path=..." where the first semicolon is before an equal
- // and a semicolon exists.
- if ((semicolonIndex != -1 && (semicolonIndex < equalIndex)) ||
- equalIndex == -1) {
- // Fix up the index in case we have a string like "testcookie"
- if (semicolonIndex == -1) {
- semicolonIndex = length;
- }
- cookie.name = cookieString.substring(index, semicolonIndex);
- cookie.value = null;
- } else {
- cookie.name = cookieString.substring(index, equalIndex);
- // Make sure we do not throw an exception if the cookie is like
- // "foo="
- if ((equalIndex < length - 1) &&
- (cookieString.charAt(equalIndex + 1) == QUOTATION)) {
- index = cookieString.indexOf(QUOTATION, equalIndex + 2);
- if (index == -1) {
- // bad format, force return
- break;
- }
- }
- // Get the semicolon index again in case it was contained within
- // the quotations.
- semicolonIndex = cookieString.indexOf(SEMICOLON, index);
- if (semicolonIndex == -1) {
- semicolonIndex = length;
- }
- if (semicolonIndex - equalIndex > MAX_COOKIE_LENGTH) {
- // cookie is too big, trim it
- cookie.value = cookieString.substring(equalIndex + 1,
- equalIndex + 1 + MAX_COOKIE_LENGTH);
- } else if (equalIndex + 1 == semicolonIndex
- || semicolonIndex < equalIndex) {
- // this is an unusual case like "foo=;" or "foo="
- cookie.value = "";
- } else {
- cookie.value = cookieString.substring(equalIndex + 1,
- semicolonIndex);
- }
- }
- // get attributes
- index = semicolonIndex;
- while (true) {
- // done
- if (index < 0 || index >= length) {
- break;
- }
-
- // skip white space and semicolon
- if (cookieString.charAt(index) == WHITE_SPACE
- || cookieString.charAt(index) == SEMICOLON) {
- index++;
- continue;
- }
-
- // comma means next cookie
- if (cookieString.charAt(index) == COMMA) {
- index++;
- break;
- }
-
- // "secure" is a known attribute doesn't use "=";
- // while sites like live.com uses "secure="
- if (length - index >= SECURE_LENGTH
- && cookieString.substring(index, index + SECURE_LENGTH).
- equalsIgnoreCase(SECURE)) {
- index += SECURE_LENGTH;
- cookie.secure = true;
- if (index == length) break;
- if (cookieString.charAt(index) == EQUAL) index++;
- continue;
- }
-
- // "httponly" is a known attribute doesn't use "=";
- // while sites like live.com uses "httponly="
- if (length - index >= HTTP_ONLY_LENGTH
- && cookieString.substring(index,
- index + HTTP_ONLY_LENGTH).
- equalsIgnoreCase(HTTP_ONLY)) {
- index += HTTP_ONLY_LENGTH;
- if (index == length) break;
- if (cookieString.charAt(index) == EQUAL) index++;
- // FIXME: currently only parse the attribute
- continue;
- }
- equalIndex = cookieString.indexOf(EQUAL, index);
- if (equalIndex > 0) {
- String name = cookieString.substring(index, equalIndex).toLowerCase();
- int valueIndex = equalIndex + 1;
- while (valueIndex < length && cookieString.charAt(valueIndex) == WHITE_SPACE) {
- valueIndex++;
- }
-
- if (name.equals(EXPIRES)) {
- int comaIndex = cookieString.indexOf(COMMA, equalIndex);
-
- // skip ',' in (Wdy, DD-Mon-YYYY HH:MM:SS GMT) or
- // (Weekday, DD-Mon-YY HH:MM:SS GMT) if it applies.
- // "Wednesday" is the longest Weekday which has length 9
- if ((comaIndex != -1) &&
- (comaIndex - valueIndex <= 10)) {
- index = comaIndex + 1;
- }
- }
- semicolonIndex = cookieString.indexOf(SEMICOLON, index);
- int commaIndex = cookieString.indexOf(COMMA, index);
- if (semicolonIndex == -1 && commaIndex == -1) {
- index = length;
- } else if (semicolonIndex == -1) {
- index = commaIndex;
- } else if (commaIndex == -1) {
- index = semicolonIndex;
- } else {
- index = Math.min(semicolonIndex, commaIndex);
- }
- String value = cookieString.substring(valueIndex, index);
-
- // Strip quotes if they exist
- if (value.length() > 2 && value.charAt(0) == QUOTATION) {
- int endQuote = value.indexOf(QUOTATION, 1);
- if (endQuote > 0) {
- value = value.substring(1, endQuote);
- }
- }
- if (name.equals(EXPIRES)) {
- try {
- cookie.expires = AndroidHttpClient.parseDate(value);
- } catch (IllegalArgumentException ex) {
- Log.e(LOGTAG,
- "illegal format for expires: " + value);
- }
- } else if (name.equals(MAX_AGE)) {
- try {
- cookie.expires = System.currentTimeMillis() + 1000
- * Long.parseLong(value);
- } catch (NumberFormatException ex) {
- Log.e(LOGTAG,
- "illegal format for max-age: " + value);
- }
- } else if (name.equals(PATH)) {
- // only allow non-empty path value
- if (value.length() > 0) {
- cookie.path = value;
- }
- } else if (name.equals(DOMAIN)) {
- int lastPeriod = value.lastIndexOf(PERIOD);
- if (lastPeriod == 0) {
- // disallow cookies set for TLDs like [.com]
- cookie.domain = null;
- continue;
- }
- try {
- Integer.parseInt(value.substring(lastPeriod + 1));
- // no wildcard for ip address match
- if (!value.equals(host)) {
- // no cross-site cookie
- cookie.domain = null;
- }
- continue;
- } catch (NumberFormatException ex) {
- // ignore the exception, value is a host name
- }
- value = value.toLowerCase();
- if (value.charAt(0) != PERIOD) {
- // pre-pended dot to make it as a domain cookie
- value = PERIOD + value;
- lastPeriod++;
- }
- if (host.endsWith(value.substring(1))) {
- int len = value.length();
- int hostLen = host.length();
- if (hostLen > (len - 1)
- && host.charAt(hostLen - len) != PERIOD) {
- // make sure the bar.com doesn't match .ar.com
- cookie.domain = null;
- continue;
- }
- // disallow cookies set on ccTLDs like [.co.uk]
- if ((len == lastPeriod + 3)
- && (len >= 6 && len <= 8)) {
- String s = value.substring(1, lastPeriod);
- if (Arrays.binarySearch(BAD_COUNTRY_2LDS, s) >= 0) {
- cookie.domain = null;
- continue;
- }
- }
- cookie.domain = value;
- } else {
- // no cross-site or more specific sub-domain cookie
- cookie.domain = null;
- }
- }
- } else {
- // bad format, force return
- index = length;
- }
- }
- if (cookie != null && cookie.domain != null) {
- ret.add(cookie);
- }
- }
- return ret;
+ nativeSetAcceptFileSchemeCookies(accept);
}
// Native functions
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index a699800..19fa096 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -100,77 +100,6 @@
return sRef;
}
- /**
- * Package level api, called from CookieManager. Get all the cookies which
- * matches a given base domain.
- * @param domain
- * @return A list of Cookie
- */
- ArrayList<Cookie> getCookiesForDomain(String domain) {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie. No sync needed.
- if (mDataBase == null) {
- return new ArrayList<Cookie>();
- }
-
- return mDataBase.getCookiesForDomain(domain);
- }
-
- /**
- * Package level api, called from CookieManager Clear all cookies in the
- * database
- */
- void clearAllCookies() {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return;
- }
-
- mDataBase.clearCookies();
- }
-
- /**
- * Returns true if there are any saved cookies.
- */
- boolean hasCookies() {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return false;
- }
-
- return mDataBase.hasCookies();
- }
-
- /**
- * Package level api, called from CookieManager Clear all session cookies in
- * the database
- */
- void clearSessionCookies() {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return;
- }
-
- mDataBase.clearSessionCookies();
- }
-
- /**
- * Package level api, called from CookieManager Clear all expired cookies in
- * the database
- */
- void clearExpiredCookies(long now) {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return;
- }
-
- mDataBase.clearExpiredCookies(now);
- }
-
protected void syncFromRamToFlash() {
if (DebugFlags.COOKIE_SYNC_MANAGER) {
Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash STARTS");
@@ -182,41 +111,13 @@
return;
}
- if (JniUtil.useChromiumHttpStack()) {
- manager.flushCookieStore();
- } else {
- ArrayList<Cookie> cookieList = manager.getUpdatedCookiesSince(mLastUpdate);
- mLastUpdate = System.currentTimeMillis();
- syncFromRamToFlash(cookieList);
-
- ArrayList<Cookie> lruList = manager.deleteLRUDomain();
- syncFromRamToFlash(lruList);
- }
+ manager.flushCookieStore();
if (DebugFlags.COOKIE_SYNC_MANAGER) {
Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash DONE");
}
}
- private void syncFromRamToFlash(ArrayList<Cookie> list) {
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.mode != Cookie.MODE_NORMAL) {
- if (cookie.mode != Cookie.MODE_NEW) {
- mDataBase.deleteCookies(cookie.domain, cookie.path,
- cookie.name);
- }
- if (cookie.mode != Cookie.MODE_DELETED) {
- mDataBase.addCookie(cookie);
- CookieManager.getInstance().syncedACookie(cookie);
- } else {
- CookieManager.getInstance().deleteACookie(cookie);
- }
- }
- }
- }
-
private static void checkInstanceIsCreated() {
if (sRef == null) {
throw new IllegalStateException(
diff --git a/core/java/android/webkit/DataLoader.java b/core/java/android/webkit/DataLoader.java
deleted file mode 100644
index e8d9069..0000000
--- a/core/java/android/webkit/DataLoader.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.EventHandler;
-
-import com.android.internal.R;
-
-import java.io.ByteArrayInputStream;
-
-import libcore.io.Base64;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses the
- * content supplied as a URL as the source for the stream. The mimetype
- * optionally provided in the URL is extracted and inserted into the HTTP
- * response headers.
- */
-class DataLoader extends StreamLoader {
-
- /**
- * Constructor uses the dataURL as the source for an InputStream
- * @param dataUrl data: URL string optionally containing a mimetype
- * @param loadListener LoadListener to pass the content to
- */
- DataLoader(String dataUrl, LoadListener loadListener) {
- super(loadListener);
-
- String url = dataUrl.substring("data:".length());
- byte[] data = null;
- int commaIndex = url.indexOf(',');
- if (commaIndex != -1) {
- String contentType = url.substring(0, commaIndex);
- data = url.substring(commaIndex + 1).getBytes();
- loadListener.parseContentTypeHeader(contentType);
- if ("base64".equals(loadListener.transferEncoding())) {
- data = Base64.decode(data);
- }
- } else {
- data = url.getBytes();
- }
- if (data != null) {
- mDataStream = new ByteArrayInputStream(data);
- mContentLength = data.length;
- }
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- if (mDataStream != null) {
- mLoadListener.status(1, 1, 200, "OK");
- return true;
- } else {
- mLoadListener.error(EventHandler.ERROR,
- mContext.getString(R.string.httpError));
- return false;
- }
- }
-
- @Override
- protected void buildHeaders(android.net.http.Headers h) {
- }
-}
diff --git a/core/java/android/webkit/FileLoader.java b/core/java/android/webkit/FileLoader.java
deleted file mode 100644
index e21e9ef..0000000
--- a/core/java/android/webkit/FileLoader.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import com.android.internal.R;
-
-import android.content.res.AssetManager;
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.util.Log;
-import android.util.TypedValue;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.lang.reflect.Field;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses a
- * file or asset as the source for the stream.
- *
- */
-class FileLoader extends StreamLoader {
-
- private String mPath; // Full path to the file to load
- private int mType; // Indicates the type of the load
- private boolean mAllowFileAccess; // Allow/block file system access
-
- // used for files under asset directory
- static final int TYPE_ASSET = 1;
- // used for files under res directory
- static final int TYPE_RES = 2;
- // generic file
- static final int TYPE_FILE = 3;
-
- private static final String LOGTAG = "webkit";
-
- /**
- * Construct a FileLoader with the file URL specified as the content
- * source.
- *
- * @param url Full file url pointing to content to be loaded
- * @param loadListener LoadListener to pass the content to
- * @param asset true if url points to an asset.
- * @param allowFileAccess true if this WebView is allowed to access files
- * on the file system.
- */
- FileLoader(String url, LoadListener loadListener, int type,
- boolean allowFileAccess) {
- super(loadListener);
- mType = type;
- mAllowFileAccess = allowFileAccess;
-
- // clean the Url
- int index = url.indexOf('?');
- if (mType == TYPE_ASSET) {
- mPath = index > 0 ? URLUtil.stripAnchor(
- url.substring(URLUtil.ASSET_BASE.length(), index)) :
- URLUtil.stripAnchor(url.substring(
- URLUtil.ASSET_BASE.length()));
- } else if (mType == TYPE_RES) {
- mPath = index > 0 ? URLUtil.stripAnchor(
- url.substring(URLUtil.RESOURCE_BASE.length(), index)) :
- URLUtil.stripAnchor(url.substring(
- URLUtil.RESOURCE_BASE.length()));
- } else {
- mPath = index > 0 ? URLUtil.stripAnchor(
- url.substring(URLUtil.FILE_BASE.length(), index)) :
- URLUtil.stripAnchor(url.substring(
- URLUtil.FILE_BASE.length()));
- }
- }
-
- private String errString(Exception ex) {
- String exMessage = ex.getMessage();
- String errString = mContext.getString(R.string.httpErrorFileNotFound);
- if (exMessage != null) {
- errString += " " + exMessage;
- }
- return errString;
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- try {
- if (mType == TYPE_ASSET) {
- try {
- mDataStream = mContext.getAssets().open(mPath);
- } catch (java.io.FileNotFoundException ex) {
- // try the rest files included in the package
- mDataStream = mContext.getAssets().openNonAsset(mPath);
- }
- } else if (mType == TYPE_RES) {
- // get the resource id from the path. e.g. for the path like
- // drawable/foo.png, the id is located at field "foo" of class
- // "<package>.R$drawable"
- if (mPath == null || mPath.length() == 0) {
- Log.e(LOGTAG, "Need a path to resolve the res file");
- mLoadListener.error(EventHandler.FILE_ERROR, mContext
- .getString(R.string.httpErrorFileNotFound));
- return false;
-
- }
- int slash = mPath.indexOf('/');
- int dot = mPath.indexOf('.', slash);
- if (slash == -1 || dot == -1) {
- Log.e(LOGTAG, "Incorrect res path: " + mPath);
- mLoadListener.error(EventHandler.FILE_ERROR, mContext
- .getString(R.string.httpErrorFileNotFound));
- return false;
- }
- String subClassName = mPath.substring(0, slash);
- String fieldName = mPath.substring(slash + 1, dot);
- String errorMsg = null;
- try {
- final Class<?> d = mContext.getApplicationContext()
- .getClassLoader().loadClass(
- mContext.getPackageName() + ".R$"
- + subClassName);
- final Field field = d.getField(fieldName);
- final int id = field.getInt(null);
- TypedValue value = new TypedValue();
- mContext.getResources().getValue(id, value, true);
- if (value.type == TypedValue.TYPE_STRING) {
- mDataStream = mContext.getAssets().openNonAsset(
- value.assetCookie, value.string.toString(),
- AssetManager.ACCESS_STREAMING);
- } else {
- errorMsg = "Only support TYPE_STRING for the res files";
- }
- } catch (ClassNotFoundException e) {
- errorMsg = "Can't find class: "
- + mContext.getPackageName() + ".R$" + subClassName;
- } catch (SecurityException e) {
- errorMsg = "Caught SecurityException: " + e;
- } catch (NoSuchFieldException e) {
- errorMsg = "Can't find field: " + fieldName + " in "
- + mContext.getPackageName() + ".R$" + subClassName;
- } catch (IllegalArgumentException e) {
- errorMsg = "Caught IllegalArgumentException: " + e;
- } catch (IllegalAccessException e) {
- errorMsg = "Caught IllegalAccessException: " + e;
- }
- if (errorMsg != null) {
- mLoadListener.error(EventHandler.FILE_ERROR, mContext
- .getString(R.string.httpErrorFileNotFound));
- return false;
- }
- } else {
- if (!mAllowFileAccess) {
- mLoadListener.error(EventHandler.FILE_ERROR,
- mContext.getString(R.string.httpErrorFileNotFound));
- return false;
- }
-
- mDataStream = new FileInputStream(mPath);
- mContentLength = (new File(mPath)).length();
- }
- mLoadListener.status(1, 1, 200, "OK");
-
- } catch (java.io.FileNotFoundException ex) {
- mLoadListener.error(EventHandler.FILE_NOT_FOUND_ERROR, errString(ex));
- return false;
-
- } catch (java.io.IOException ex) {
- mLoadListener.error(EventHandler.FILE_ERROR, errString(ex));
- return false;
- }
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- // do nothing.
- }
-}
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
deleted file mode 100644
index 0d80302..0000000
--- a/core/java/android/webkit/FrameLoader.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.ErrorStrings;
-import android.net.http.EventHandler;
-import android.net.http.RequestHandle;
-import android.os.Build;
-import android.util.Log;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.JniUtil;
-
-import java.util.HashMap;
-import java.util.Map;
-
-class FrameLoader {
-
- private final LoadListener mListener;
- private final String mMethod;
- private final WebSettings mSettings;
- private Map<String, String> mHeaders;
- private byte[] mPostData;
- private Network mNetwork;
- private int mCacheMode;
- private String mReferrer;
- private String mContentType;
- private final String mUaprofHeader;
- private final WebResourceResponse mInterceptResponse;
-
- private static final int URI_PROTOCOL = 0x100;
-
- private static final String CONTENT_TYPE = "content-type";
-
- // Contents of an about:blank page
- private static final String mAboutBlank =
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EB\">" +
- "<html><head><title>about:blank</title></head><body></body></html>";
-
- static final String HEADER_STR = "text/xml, text/html, " +
- "application/xhtml+xml, image/png, text/plain, */*;q=0.8";
-
- private static final String LOGTAG = "webkit";
-
- FrameLoader(LoadListener listener, WebSettings settings,
- String method, WebResourceResponse interceptResponse) {
- assert !JniUtil.useChromiumHttpStack();
-
- mListener = listener;
- mHeaders = null;
- mMethod = method;
- mCacheMode = WebSettings.LOAD_NORMAL;
- mSettings = settings;
- mInterceptResponse = interceptResponse;
- mUaprofHeader = mListener.getContext().getResources().getString(
- com.android.internal.R.string.config_useragentprofile_url, Build.MODEL);
- }
-
- public void setReferrer(String ref) {
- // only set referrer for http or https
- if (URLUtil.isNetworkUrl(ref)) mReferrer = ref;
- }
-
- public void setPostData(byte[] postData) {
- mPostData = postData;
- }
-
- public void setContentTypeForPost(String postContentType) {
- mContentType = postContentType;
- }
-
- public void setCacheMode(int cacheMode) {
- mCacheMode = cacheMode;
- }
-
- public void setHeaders(HashMap headers) {
- mHeaders = headers;
- }
-
- public LoadListener getLoadListener() {
- return mListener;
- }
-
- /**
- * Issues the load request.
- *
- * Return value does not indicate if the load was successful or not. It
- * simply indicates that the load request is reasonable.
- *
- * @return true if the load is reasonable.
- */
- public boolean executeLoad() {
- String url = mListener.url();
-
- // Process intercepted requests first as they could be any url.
- if (mInterceptResponse != null) {
- if (mListener.isSynchronous()) {
- mInterceptResponse.loader(mListener).load();
- } else {
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER,
- mInterceptResponse.loader(mListener)).sendToTarget();
- }
- return true;
- } else if (URLUtil.isNetworkUrl(url)){
- if (mSettings.getBlockNetworkLoads()) {
- mListener.error(EventHandler.ERROR_BAD_URL,
- mListener.getContext().getString(
- com.android.internal.R.string.httpErrorBadUrl));
- return false;
- }
- // Make sure the host part of the url is correctly
- // encoded before sending the request
- if (!URLUtil.verifyURLEncoding(mListener.host())) {
- mListener.error(EventHandler.ERROR_BAD_URL,
- mListener.getContext().getString(
- com.android.internal.R.string.httpErrorBadUrl));
- return false;
- }
- mNetwork = Network.getInstance(mListener.getContext());
- if (mListener.isSynchronous()) {
- return handleHTTPLoad();
- }
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_HTTPLOADER, this).sendToTarget();
- return true;
- } else if (handleLocalFile(url, mListener, mSettings)) {
- return true;
- }
- if (DebugFlags.FRAME_LOADER) {
- Log.v(LOGTAG, "FrameLoader.executeLoad: url protocol not supported:"
- + mListener.url());
- }
- mListener.error(EventHandler.ERROR_UNSUPPORTED_SCHEME,
- mListener.getContext().getText(
- com.android.internal.R.string.httpErrorUnsupportedScheme).toString());
- return false;
-
- }
-
- private static boolean handleLocalFile(String url, LoadListener loadListener,
- WebSettings settings) {
- assert !JniUtil.useChromiumHttpStack();
-
- // Attempt to decode the percent-encoded url before passing to the
- // local loaders.
- try {
- url = new String(URLUtil.decode(url.getBytes()));
- } catch (IllegalArgumentException e) {
- loadListener.error(EventHandler.ERROR_BAD_URL,
- loadListener.getContext().getString(
- com.android.internal.R.string.httpErrorBadUrl));
- // Return true here so we do not trigger an unsupported scheme
- // error.
- return true;
- }
- if (URLUtil.isAssetUrl(url)) {
- if (loadListener.isSynchronous()) {
- new FileLoader(url, loadListener, FileLoader.TYPE_ASSET,
- true).load();
- } else {
- // load asset in a separate thread as it involves IO
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER,
- new FileLoader(url, loadListener, FileLoader.TYPE_ASSET,
- true)).sendToTarget();
- }
- return true;
- } else if (URLUtil.isResourceUrl(url)) {
- if (loadListener.isSynchronous()) {
- new FileLoader(url, loadListener, FileLoader.TYPE_RES,
- true).load();
- } else {
- // load resource in a separate thread as it involves IO
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER,
- new FileLoader(url, loadListener, FileLoader.TYPE_RES,
- true)).sendToTarget();
- }
- return true;
- } else if (URLUtil.isFileUrl(url)) {
- if (loadListener.isSynchronous()) {
- new FileLoader(url, loadListener, FileLoader.TYPE_FILE,
- settings.getAllowFileAccess()).load();
- } else {
- // load file in a separate thread as it involves IO
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER,
- new FileLoader(url, loadListener, FileLoader.TYPE_FILE,
- settings.getAllowFileAccess())).sendToTarget();
- }
- return true;
- } else if (settings.getAllowContentAccess() &&
- URLUtil.isContentUrl(url)) {
- // Send the raw url to the ContentLoader because it will do a
- // permission check and the url has to match.
- if (loadListener.isSynchronous()) {
- new ContentLoader(loadListener.url(), loadListener).load();
- } else {
- // load content in a separate thread as it involves IO
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER,
- new ContentLoader(loadListener.url(), loadListener))
- .sendToTarget();
- }
- return true;
- } else if (URLUtil.isDataUrl(url)) {
- // load data in the current thread to reduce the latency
- new DataLoader(url, loadListener).load();
- return true;
- } else if (URLUtil.isAboutUrl(url)) {
- loadListener.data(mAboutBlank.getBytes(), mAboutBlank.length());
- loadListener.endData();
- return true;
- }
- return false;
- }
-
- boolean handleHTTPLoad() {
- if (mHeaders == null) {
- mHeaders = new HashMap<String, String>();
- }
- populateStaticHeaders();
- populateHeaders();
-
- // response was handled by Cache, don't issue HTTP request
- if (handleCache()) {
- // push the request data down to the LoadListener
- // as response from the cache could be a redirect
- // and we may need to initiate a network request if the cache
- // can't satisfy redirect URL
- mListener.setRequestData(mMethod, mHeaders, mPostData);
- return true;
- }
-
- if (DebugFlags.FRAME_LOADER) {
- Log.v(LOGTAG, "FrameLoader: http " + mMethod + " load for: "
- + mListener.url());
- }
-
- boolean ret = false;
- int error = EventHandler.ERROR_UNSUPPORTED_SCHEME;
-
- try {
- ret = mNetwork.requestURL(mMethod, mHeaders,
- mPostData, mListener);
- } catch (android.net.ParseException ex) {
- error = EventHandler.ERROR_BAD_URL;
- } catch (java.lang.RuntimeException ex) {
- /* probably an empty header set by javascript. We want
- the same result as bad URL */
- error = EventHandler.ERROR_BAD_URL;
- }
- if (!ret) {
- mListener.error(error, ErrorStrings.getString(error, mListener.getContext()));
- return false;
- }
- return true;
- }
-
- /*
- * This function is used by handleCache to
- * setup a load from the byte stream in a CacheResult.
- */
- private void startCacheLoad(CacheResult result) {
- if (DebugFlags.FRAME_LOADER) {
- Log.v(LOGTAG, "FrameLoader: loading from cache: "
- + mListener.url());
- }
- // Tell the Listener respond with the cache file
- CacheLoader cacheLoader =
- new CacheLoader(mListener, result);
- mListener.setCacheLoader(cacheLoader);
- if (mListener.isSynchronous()) {
- cacheLoader.load();
- } else {
- // Load the cached file in a separate thread
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER, cacheLoader).sendToTarget();
- }
- }
-
- /*
- * This function is used by the handleHTTPLoad to setup the cache headers
- * correctly.
- * Returns true if the response was handled from the cache
- */
- private boolean handleCache() {
- switch (mCacheMode) {
- // This mode is normally used for a reload, it instructs the http
- // loader to not use the cached content.
- case WebSettings.LOAD_NO_CACHE:
- break;
-
-
- // This mode is used when the content should only be loaded from
- // the cache. If it is not there, then fail the load. This is used
- // to load POST content in a history navigation.
- case WebSettings.LOAD_CACHE_ONLY: {
- CacheResult result = CacheManager.getCacheFile(mListener.url(),
- mListener.postIdentifier(), null);
- if (result != null) {
- startCacheLoad(result);
- } else {
- // This happens if WebCore was first told that the POST
- // response was in the cache, then when we try to use it
- // it has gone.
- // Generate a file not found error
- int err = EventHandler.FILE_NOT_FOUND_ERROR;
- mListener.error(err,
- ErrorStrings.getString(err, mListener.getContext()));
- }
- return true;
- }
-
- // This mode is for when the user is doing a history navigation
- // in the browser and should returned cached content regardless
- // of it's state. If it is not in the cache, then go to the
- // network.
- case WebSettings.LOAD_CACHE_ELSE_NETWORK: {
- if (DebugFlags.FRAME_LOADER) {
- Log.v(LOGTAG, "FrameLoader: checking cache: "
- + mListener.url());
- }
- // Get the cache file name for the current URL, passing null for
- // the validation headers causes no validation to occur
- CacheResult result = CacheManager.getCacheFile(mListener.url(),
- mListener.postIdentifier(), null);
- if (result != null) {
- startCacheLoad(result);
- return true;
- }
- break;
- }
-
- // This is the default case, which is to check to see if the
- // content in the cache can be used. If it can be used, then
- // use it. If it needs revalidation then the relevant headers
- // are added to the request.
- default:
- case WebSettings.LOAD_NORMAL:
- return mListener.checkCache(mHeaders);
- }// end of switch
-
- return false;
- }
-
- /**
- * Add the static headers that don't change with each request.
- */
- private void populateStaticHeaders() {
- // Accept header should already be there as they are built by WebCore,
- // but in the case they are missing, add some.
- String accept = mHeaders.get("Accept");
- if (accept == null || accept.length() == 0) {
- mHeaders.put("Accept", HEADER_STR);
- }
- mHeaders.put("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");
-
- String acceptLanguage = mSettings.getAcceptLanguage();
- if (acceptLanguage.length() > 0) {
- mHeaders.put("Accept-Language", acceptLanguage);
- }
-
- mHeaders.put("User-Agent", mSettings.getUserAgentString());
-
- // Set the x-wap-profile header
- if (mUaprofHeader != null && mUaprofHeader.length() > 0) {
- mHeaders.put("x-wap-profile", mUaprofHeader);
- }
- }
-
- /**
- * Add the content related headers. These headers contain user private data
- * and is not used when we are proxying an untrusted request.
- */
- private void populateHeaders() {
-
- if (mReferrer != null) mHeaders.put("Referer", mReferrer);
- if (mContentType != null) mHeaders.put(CONTENT_TYPE, mContentType);
-
- // if we have an active proxy and have proxy credentials, do pre-emptive
- // authentication to avoid an extra round-trip:
- if (mNetwork.isValidProxySet()) {
- String username;
- String password;
- /* The proxy credentials can be set in the Network thread */
- synchronized (mNetwork) {
- username = mNetwork.getProxyUsername();
- password = mNetwork.getProxyPassword();
- }
- if (username != null && password != null) {
- // we collect credentials ONLY if the proxy scheme is BASIC!!!
- String proxyHeader = RequestHandle.authorizationHeader(true);
- mHeaders.put(proxyHeader,
- "Basic " + RequestHandle.computeBasicAuthResponse(
- username, password));
- }
- }
-
- // Set cookie header
- String cookie = CookieManager.getInstance().getCookie(
- mListener.getWebAddress());
- if (cookie != null && cookie.length() > 0) {
- mHeaders.put("Cookie", cookie);
- }
- }
-}
diff --git a/core/java/android/webkit/HttpAuthHandlerImpl.java b/core/java/android/webkit/HttpAuthHandlerImpl.java
deleted file mode 100644
index 01e8eb8..0000000
--- a/core/java/android/webkit/HttpAuthHandlerImpl.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-import java.util.ListIterator;
-import java.util.LinkedList;
-
-/**
- * HttpAuthHandler implementation is used only by the Android Java HTTP stack.
- * <p>
- * This class is not needed when we're using the Chromium HTTP stack.
- */
-class HttpAuthHandlerImpl extends HttpAuthHandler {
- /*
- * It is important that the handler is in Network, because we want to share
- * it accross multiple loaders and windows (like our subwindow and the main
- * window).
- */
-
- private static final String LOGTAG = "network";
-
- /**
- * Network.
- */
- private Network mNetwork;
-
- /**
- * Loader queue.
- */
- private LinkedList<LoadListener> mLoaderQueue;
-
-
- // Message id for handling the user response
- private static final int AUTH_PROCEED = 100;
- private static final int AUTH_CANCEL = 200;
-
- // Use to synchronize when making synchronous calls to
- // onReceivedHttpAuthRequest(). We can't use a single Boolean object for
- // both the lock and the state, because Boolean is immutable.
- Object mRequestInFlightLock = new Object();
- boolean mRequestInFlight;
- String mUsername;
- String mPassword;
-
- /**
- * Creates a new HTTP authentication handler with an empty
- * loader queue
- *
- * @param network The parent network object
- */
- /* package */ HttpAuthHandlerImpl(Network network) {
- mNetwork = network;
- mLoaderQueue = new LinkedList<LoadListener>();
- }
-
-
- @Override
- public void handleMessage(Message msg) {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.poll();
- }
- assert(loader.isSynchronous() == false);
-
- switch (msg.what) {
- case AUTH_PROCEED:
- String username = msg.getData().getString("username");
- String password = msg.getData().getString("password");
-
- loader.handleAuthResponse(username, password);
- break;
-
- case AUTH_CANCEL:
- loader.handleAuthResponse(null, null);
- break;
- }
-
- processNextLoader();
- }
-
- /**
- * Helper method used to unblock handleAuthRequest(), which in the case of a
- * synchronous request will wait for proxy.onReceivedHttpAuthRequest() to
- * call back to either proceed() or cancel().
- *
- * @param username The username to use for authentication
- * @param password The password to use for authentication
- * @return True if the request is synchronous and handleAuthRequest() has
- * been unblocked
- */
- private boolean handleResponseForSynchronousRequest(String username, String password) {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.peek();
- }
- if (loader.isSynchronous()) {
- mUsername = username;
- mPassword = password;
- return true;
- }
- return false;
- }
-
- private void signalRequestComplete() {
- synchronized (mRequestInFlightLock) {
- assert(mRequestInFlight);
- mRequestInFlight = false;
- mRequestInFlightLock.notify();
- }
- }
-
- /**
- * Proceed with the authorization with the given credentials
- *
- * May be called on the UI thread, rather than the WebCore thread.
- *
- * @param username The username to use for authentication
- * @param password The password to use for authentication
- */
- public void proceed(String username, String password) {
- if (handleResponseForSynchronousRequest(username, password)) {
- signalRequestComplete();
- return;
- }
- Message msg = obtainMessage(AUTH_PROCEED);
- msg.getData().putString("username", username);
- msg.getData().putString("password", password);
- sendMessage(msg);
- signalRequestComplete();
- }
-
- /**
- * Cancel the authorization request
- *
- * May be called on the UI thread, rather than the WebCore thread.
- *
- */
- public void cancel() {
- if (handleResponseForSynchronousRequest(null, null)) {
- signalRequestComplete();
- return;
- }
- sendMessage(obtainMessage(AUTH_CANCEL));
- signalRequestComplete();
- }
-
- /**
- * @return True if we can use user credentials on record
- * (ie, if we did not fail trying to use them last time)
- */
- public boolean useHttpAuthUsernamePassword() {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.peek();
- }
- if (loader != null) {
- return !loader.authCredentialsInvalid();
- }
-
- return false;
- }
-
- /**
- * Enqueues the loader, if the loader is the only element
- * in the queue, starts processing the loader
- *
- * @param loader The loader that resulted in this http
- * authentication request
- */
- /* package */ void handleAuthRequest(LoadListener loader) {
- // The call to proxy.onReceivedHttpAuthRequest() may be asynchronous. If
- // the request is synchronous, we must block here until we have a
- // response.
- if (loader.isSynchronous()) {
- // If there's a request in flight, wait for it to complete. The
- // response will queue a message on this thread.
- waitForRequestToComplete();
- // Make a request to the proxy for this request, jumping the queue.
- // We use the queue so that the loader is present in
- // useHttpAuthUsernamePassword().
- synchronized (mLoaderQueue) {
- mLoaderQueue.addFirst(loader);
- }
- processNextLoader();
- // Wait for this request to complete.
- waitForRequestToComplete();
- // Pop the loader from the queue.
- synchronized (mLoaderQueue) {
- assert(mLoaderQueue.peek() == loader);
- mLoaderQueue.poll();
- }
- // Call back.
- loader.handleAuthResponse(mUsername, mPassword);
- // The message queued by the response from the last asynchronous
- // request, if present, will start the next request.
- return;
- }
-
- boolean processNext = false;
-
- synchronized (mLoaderQueue) {
- mLoaderQueue.offer(loader);
- processNext =
- (mLoaderQueue.size() == 1);
- }
-
- if (processNext) {
- processNextLoader();
- }
- }
-
- /**
- * Wait for the request in flight, if any, to complete
- */
- private void waitForRequestToComplete() {
- synchronized (mRequestInFlightLock) {
- while (mRequestInFlight) {
- try {
- mRequestInFlightLock.wait();
- } catch(InterruptedException e) {
- Log.e(LOGTAG, "Interrupted while waiting for request to complete");
- }
- }
- }
- }
-
- /**
- * Process the next loader in the queue (helper method)
- */
- private void processNextLoader() {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.peek();
- }
- if (loader != null) {
- synchronized (mRequestInFlightLock) {
- assert(mRequestInFlight == false);
- mRequestInFlight = true;
- }
-
- CallbackProxy proxy = loader.getFrame().getCallbackProxy();
-
- String hostname = loader.proxyAuthenticate() ?
- mNetwork.getProxyHostname() : loader.host();
-
- String realm = loader.realm();
-
- proxy.onReceivedHttpAuthRequest(this, hostname, realm);
- }
- }
-
- /**
- * Informs the WebView of a new set of credentials.
- */
- public static void onReceivedCredentials(LoadListener loader,
- String host, String realm, String username, String password) {
- CallbackProxy proxy = loader.getFrame().getCallbackProxy();
- proxy.onReceivedHttpAuthCredentials(host, realm, username, password);
- }
-}
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index 7b44938..343d34a 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -37,7 +37,6 @@
// Used by the Chromium HTTP stack.
private static String sDatabaseDirectory;
private static String sCacheDirectory;
- private static Boolean sUseChromiumHttpStack;
private static Context sContext;
private static void checkInitialized() {
@@ -111,10 +110,9 @@
// content://
if (url.startsWith(ANDROID_CONTENT)) {
try {
- // Strip off mimetype, for compatibility with ContentLoader.java
- // If we don't do this, we can fail to load Gmail attachments,
- // because the URL being loaded doesn't exactly match the URL we
- // have permission to read.
+ // Strip off MIME type. If we don't do this, we can fail to
+ // load Gmail attachments, because the URL being loaded doesn't
+ // exactly match the URL we have permission to read.
int mimeIndex = url.lastIndexOf('?');
if (mimeIndex != -1) {
url = url.substring(0, mimeIndex);
@@ -152,6 +150,7 @@
if (url.startsWith(ANDROID_CONTENT)) {
try {
// Strip off mimetype, for compatibility with ContentLoader.java
+ // (used with Android HTTP stack, now removed).
// If we don't do this, we can fail to load Gmail attachments,
// because the URL being loaded doesn't exactly match the URL we
// have permission to read.
@@ -170,19 +169,6 @@
}
}
- /**
- * Returns true if we're using the Chromium HTTP stack.
- *
- * TODO: Remove this if/when we permanently switch to the Chromium HTTP stack
- * http:/b/3118772
- */
- static boolean useChromiumHttpStack() {
- if (sUseChromiumHttpStack == null) {
- sUseChromiumHttpStack = nativeUseChromiumHttpStack();
- }
- return sUseChromiumHttpStack;
- }
-
private static synchronized String getAutofillQueryUrl() {
checkInitialized();
// If the device has not checked in it won't have pulled down the system setting for the
@@ -200,7 +186,4 @@
long leftToAllocate = memInfo.availMem - memInfo.threshold;
return !memInfo.lowMemory && bytesRequested < leftToAllocate;
}
-
-
- private static native boolean nativeUseChromiumHttpStack();
}
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
deleted file mode 100644
index 4d7ade5..0000000
--- a/core/java/android/webkit/LoadListener.java
+++ /dev/null
@@ -1,1685 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.ParseException;
-import android.net.Uri;
-import android.net.WebAddress;
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.net.http.HttpAuthHeader;
-import android.net.http.RequestHandle;
-import android.net.http.SslCertificate;
-import android.net.http.SslError;
-
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.JniUtil;
-
-import com.android.internal.R;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-class LoadListener extends Handler implements EventHandler {
-
- private static final String LOGTAG = "webkit";
-
- // Messages used internally to communicate state between the
- // Network thread and the WebCore thread.
- private static final int MSG_CONTENT_HEADERS = 100;
- private static final int MSG_CONTENT_DATA = 110;
- private static final int MSG_CONTENT_FINISHED = 120;
- private static final int MSG_CONTENT_ERROR = 130;
- private static final int MSG_LOCATION_CHANGED = 140;
- private static final int MSG_LOCATION_CHANGED_REQUEST = 150;
- private static final int MSG_STATUS = 160;
- private static final int MSG_SSL_CERTIFICATE = 170;
- private static final int MSG_SSL_ERROR = 180;
-
- // Standard HTTP status codes in a more representative format
- private static final int HTTP_OK = 200;
- private static final int HTTP_PARTIAL_CONTENT = 206;
- private static final int HTTP_MOVED_PERMANENTLY = 301;
- private static final int HTTP_FOUND = 302;
- private static final int HTTP_SEE_OTHER = 303;
- private static final int HTTP_NOT_MODIFIED = 304;
- private static final int HTTP_TEMPORARY_REDIRECT = 307;
- private static final int HTTP_AUTH = 401;
- private static final int HTTP_NOT_FOUND = 404;
- private static final int HTTP_PROXY_AUTH = 407;
-
- private static int sNativeLoaderCount;
-
- private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder();
-
- private String mUrl;
- private WebAddress mUri;
- private boolean mPermanent;
- private String mOriginalUrl;
- private Context mContext;
- private BrowserFrame mBrowserFrame;
- private int mNativeLoader;
- private String mMimeType;
- private String mEncoding;
- private String mTransferEncoding;
- private int mStatusCode;
- private String mStatusText;
- public long mContentLength; // Content length of the incoming data
- private boolean mCancelled; // The request has been cancelled.
- private boolean mAuthFailed; // indicates that the prev. auth failed
- private CacheLoader mCacheLoader;
- private boolean mFromCache = false;
- private HttpAuthHeader mAuthHeader;
- private int mErrorID = OK;
- private String mErrorDescription;
- private SslError mSslError;
- private RequestHandle mRequestHandle;
- private RequestHandle mSslErrorRequestHandle;
- private long mPostIdentifier;
- private boolean mSetNativeResponse;
-
- // Request data. It is only valid when we are doing a load from the
- // cache. It is needed if the cache returns a redirect
- private String mMethod;
- private Map<String, String> mRequestHeaders;
- private byte[] mPostData;
- // Flag to indicate that this load is synchronous.
- private boolean mSynchronous;
- private Vector<Message> mMessageQueue;
-
- // Does this loader correspond to the main-frame top-level page?
- private boolean mIsMainPageLoader;
- // Does this loader correspond to the main content (as opposed to a supporting resource)
- private final boolean mIsMainResourceLoader;
- private final boolean mUserGesture;
-
- private Headers mHeaders;
-
- private final String mUsername;
- private final String mPassword;
-
- // =========================================================================
- // Public functions
- // =========================================================================
-
- public static LoadListener getLoadListener(Context context,
- BrowserFrame frame, String url, int nativeLoader,
- boolean synchronous, boolean isMainPageLoader,
- boolean isMainResource, boolean userGesture, long postIdentifier,
- String username, String password) {
-
- sNativeLoaderCount += 1;
- return new LoadListener(context, frame, url, nativeLoader, synchronous,
- isMainPageLoader, isMainResource, userGesture, postIdentifier,
- username, password);
- }
-
- public static int getNativeLoaderCount() {
- return sNativeLoaderCount;
- }
-
- LoadListener(Context context, BrowserFrame frame, String url,
- int nativeLoader, boolean synchronous, boolean isMainPageLoader,
- boolean isMainResource, boolean userGesture, long postIdentifier,
- String username, String password) {
- assert !JniUtil.useChromiumHttpStack();
-
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener constructor url=" + url);
- }
- mContext = context;
- mBrowserFrame = frame;
- setUrl(url);
- mNativeLoader = nativeLoader;
- mSynchronous = synchronous;
- if (synchronous) {
- mMessageQueue = new Vector<Message>();
- }
- mIsMainPageLoader = isMainPageLoader;
- mIsMainResourceLoader = isMainResource;
- mUserGesture = userGesture;
- mPostIdentifier = postIdentifier;
- mUsername = username;
- mPassword = password;
- }
-
- /**
- * We keep a count of refs to the nativeLoader so we do not create
- * so many LoadListeners that the GREFs blow up
- */
- private void clearNativeLoader() {
- sNativeLoaderCount -= 1;
- mNativeLoader = 0;
- mSetNativeResponse = false;
- }
-
- /*
- * This message handler is to facilitate communication between the network
- * thread and the browser thread.
- */
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_CONTENT_HEADERS:
- /*
- * This message is sent when the LoadListener has headers
- * available. The headers are sent onto WebCore to see what we
- * should do with them.
- */
- handleHeaders((Headers) msg.obj);
- break;
-
- case MSG_CONTENT_DATA:
- /*
- * This message is sent when the LoadListener has data available
- * in it's data buffer. This data buffer could be filled from a
- * file (this thread) or from http (Network thread).
- */
- if (mNativeLoader != 0 && !ignoreCallbacks()) {
- commitLoad();
- }
- break;
-
- case MSG_CONTENT_FINISHED:
- /*
- * This message is sent when the LoadListener knows that the
- * load is finished. This message is not sent in the case of an
- * error.
- *
- */
- handleEndData();
- break;
-
- case MSG_CONTENT_ERROR:
- /*
- * This message is sent when a load error has occured. The
- * LoadListener will clean itself up.
- */
- handleError(msg.arg1, (String) msg.obj);
- break;
-
- case MSG_LOCATION_CHANGED:
- /*
- * This message is sent from LoadListener.endData to inform the
- * browser activity that the location of the top level page
- * changed.
- */
- doRedirect();
- break;
-
- case MSG_LOCATION_CHANGED_REQUEST:
- /*
- * This message is sent from endData on receipt of a 307
- * Temporary Redirect in response to a POST -- the user must
- * confirm whether to continue loading. If the user says Yes,
- * we simply call MSG_LOCATION_CHANGED. If the user says No,
- * we call MSG_CONTENT_FINISHED.
- */
- Message contMsg = obtainMessage(MSG_LOCATION_CHANGED);
- Message stopMsg = obtainMessage(MSG_CONTENT_FINISHED);
- mBrowserFrame.getCallbackProxy().onFormResubmission(
- stopMsg, contMsg);
- break;
-
- case MSG_STATUS:
- /*
- * This message is sent from the network thread when the http
- * stack has received the status response from the server.
- */
- HashMap status = (HashMap) msg.obj;
- handleStatus(((Integer) status.get("major")).intValue(),
- ((Integer) status.get("minor")).intValue(),
- ((Integer) status.get("code")).intValue(),
- (String) status.get("reason"));
- break;
-
- case MSG_SSL_CERTIFICATE:
- /*
- * This message is sent when the network thread receives a ssl
- * certificate.
- */
- handleCertificate((SslCertificate) msg.obj);
- break;
-
- case MSG_SSL_ERROR:
- /*
- * This message is sent when the network thread encounters a
- * ssl error.
- */
- handleSslError((SslError) msg.obj);
- break;
- }
- }
-
- /**
- * @return The loader's BrowserFrame.
- */
- BrowserFrame getFrame() {
- return mBrowserFrame;
- }
-
- Context getContext() {
- return mContext;
- }
-
- /* package */ boolean isSynchronous() {
- return mSynchronous;
- }
-
- /**
- * @return True iff the load has been cancelled
- */
- public boolean cancelled() {
- return mCancelled;
- }
-
- /**
- * Parse the headers sent from the server.
- * @param headers gives up the HeaderGroup
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void headers(Headers headers) {
- if (DebugFlags.LOAD_LISTENER) Log.v(LOGTAG, "LoadListener.headers");
- // call db (setCookie) in the non-WebCore thread
- if (mCancelled) return;
- ArrayList<String> cookies = headers.getSetCookie();
- for (int i = 0; i < cookies.size(); ++i) {
- CookieManager.getInstance().setCookie(mUri, cookies.get(i));
- }
- sendMessageInternal(obtainMessage(MSG_CONTENT_HEADERS, headers));
- }
-
- // This is the same regex that DOMImplementation uses to check for xml
- // content. Use this to check if another Activity wants to handle the
- // content before giving it to webkit.
- private static final String XML_MIME_TYPE =
- "^[\\w_\\-+~!$\\^{}|.%'`#&*]+/" +
- "[\\w_\\-+~!$\\^{}|.%'`#&*]+\\+xml$";
-
- // Does the header parsing work on the WebCore thread.
- private void handleHeaders(Headers headers) {
- if (mCancelled) return;
-
- // Note: the headers we care in LoadListeners, like
- // content-type/content-length, should not be updated for partial
- // content. Just skip here and go ahead with adding data.
- if (mStatusCode == HTTP_PARTIAL_CONTENT) {
- // we don't support cache for partial content yet
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
- return;
- }
-
- mHeaders = headers;
-
- long contentLength = headers.getContentLength();
- if (contentLength != Headers.NO_CONTENT_LENGTH) {
- mContentLength = contentLength;
- } else {
- mContentLength = 0;
- }
-
- String contentType = headers.getContentType();
- if (contentType != null) {
- parseContentTypeHeader(contentType);
- mMimeType = MimeTypeMap.getSingleton().remapGenericMimeType(
- mMimeType, mUrl, headers.getContentDisposition());
- } else {
- /* Often when servers respond with 304 Not Modified or a
- Redirect, then they don't specify a MIMEType. When this
- occurs, the function below is called. In the case of
- 304 Not Modified, the cached headers are used rather
- than the headers that are returned from the server. */
- guessMimeType();
- }
- // At this point, mMimeType has been set to non-null.
- if (mIsMainPageLoader && mIsMainResourceLoader && mUserGesture &&
- Pattern.matches(XML_MIME_TYPE, mMimeType) &&
- !mMimeType.equalsIgnoreCase("application/xhtml+xml")) {
- Intent i = new Intent(Intent.ACTION_VIEW);
- i.setDataAndType(Uri.parse(url()), mMimeType);
- ResolveInfo info = mContext.getPackageManager().resolveActivity(i,
- PackageManager.MATCH_DEFAULT_ONLY);
- if (info != null && !mContext.getPackageName().equals(
- info.activityInfo.packageName)) {
- // someone (other than the current app) knows how to
- // handle this mime type.
- try {
- mContext.startActivity(i);
- mBrowserFrame.stopLoading();
- return;
- } catch (ActivityNotFoundException ex) {
- // continue loading internally.
- }
- }
- }
-
- // is it an authentication request?
- boolean mustAuthenticate = (mStatusCode == HTTP_AUTH ||
- mStatusCode == HTTP_PROXY_AUTH);
- // is it a proxy authentication request?
- boolean isProxyAuthRequest = (mStatusCode == HTTP_PROXY_AUTH);
- // is this authentication request due to a failed attempt to
- // authenticate ealier?
- mAuthFailed = false;
-
- // if we tried to authenticate ourselves last time
- if (mAuthHeader != null) {
- // we failed, if we must authenticate again now and
- // we have a proxy-ness match
- mAuthFailed = (mustAuthenticate &&
- isProxyAuthRequest == mAuthHeader.isProxy());
-
- // if we did NOT fail and last authentication request was a
- // proxy-authentication request
- if (!mAuthFailed && mAuthHeader.isProxy()) {
- Network network = Network.getInstance(mContext);
- // if we have a valid proxy set
- if (network.isValidProxySet()) {
- /* The proxy credentials can be read in the WebCore thread
- */
- synchronized (network) {
- // save authentication credentials for pre-emptive proxy
- // authentication
- network.setProxyUsername(mAuthHeader.getUsername());
- network.setProxyPassword(mAuthHeader.getPassword());
- }
- }
- }
- }
-
- // it is only here that we can reset the last mAuthHeader object
- // (if existed) and start a new one!!!
- mAuthHeader = null;
- if (mustAuthenticate) {
- if (mStatusCode == HTTP_AUTH) {
- mAuthHeader = parseAuthHeader(
- headers.getWwwAuthenticate());
- } else {
- mAuthHeader = parseAuthHeader(
- headers.getProxyAuthenticate());
- // if successfully parsed the header
- if (mAuthHeader != null) {
- // mark the auth-header object as a proxy
- mAuthHeader.setProxy();
- }
- }
- }
-
- // Only create a cache file if the server has responded positively.
- if ((mStatusCode == HTTP_OK ||
- mStatusCode == HTTP_FOUND ||
- mStatusCode == HTTP_MOVED_PERMANENTLY ||
- mStatusCode == HTTP_TEMPORARY_REDIRECT) &&
- mNativeLoader != 0) {
- // for POST request, only cache the result if there is an identifier
- // associated with it. postUrl() or form submission should set the
- // identifier while XHR POST doesn't.
- if (!mFromCache && mRequestHandle != null
- && (!mRequestHandle.getMethod().equals("POST")
- || mPostIdentifier != 0)) {
- WebViewWorker.CacheCreateData data = new WebViewWorker.CacheCreateData();
- data.mListener = this;
- data.mUrl = mUrl;
- data.mMimeType = mMimeType;
- data.mStatusCode = mStatusCode;
- data.mPostId = mPostIdentifier;
- data.mHeaders = headers;
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_CREATE_CACHE, data).sendToTarget();
- }
- WebViewWorker.CacheEncoding ce = new WebViewWorker.CacheEncoding();
- ce.mEncoding = mEncoding;
- ce.mListener = this;
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_UPDATE_CACHE_ENCODING, ce).sendToTarget();
- }
- commitHeadersCheckRedirect();
- }
-
- /**
- * @return True iff this loader is in the proxy-authenticate state.
- */
- boolean proxyAuthenticate() {
- if (mAuthHeader != null) {
- return mAuthHeader.isProxy();
- }
-
- return false;
- }
-
- /**
- * Report the status of the response.
- * TODO: Comments about each parameter.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void status(int majorVersion, int minorVersion,
- int code, /* Status-Code value */ String reasonPhrase) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener: from: " + mUrl
- + " major: " + majorVersion
- + " minor: " + minorVersion
- + " code: " + code
- + " reason: " + reasonPhrase);
- }
- HashMap status = new HashMap();
- status.put("major", majorVersion);
- status.put("minor", minorVersion);
- status.put("code", code);
- status.put("reason", reasonPhrase);
- // New status means new data. Clear the old.
- mDataBuilder.clear();
- mMimeType = "";
- mEncoding = "";
- mTransferEncoding = "";
- sendMessageInternal(obtainMessage(MSG_STATUS, status));
- }
-
- // Handle the status callback on the WebCore thread.
- private void handleStatus(int major, int minor, int code, String reason) {
- if (mCancelled) return;
-
- mStatusCode = code;
- mStatusText = reason;
- mPermanent = false;
- }
-
- /**
- * Implementation of certificate handler for EventHandler. Called
- * before a resource is requested. In this context, can be called
- * multiple times if we have redirects
- *
- * IMPORTANT: as this is called from network thread, can't call
- * native directly
- *
- * @param certificate The SSL certifcate or null if the request
- * was not secure
- */
- public void certificate(SslCertificate certificate) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.certificate: " + certificate);
- }
- sendMessageInternal(obtainMessage(MSG_SSL_CERTIFICATE, certificate));
- }
-
- // Handle the certificate on the WebCore thread.
- private void handleCertificate(SslCertificate certificate) {
- // if this is main resource of the top frame
- if (mIsMainPageLoader && mIsMainResourceLoader) {
- // update the browser frame with certificate
- mBrowserFrame.certificate(certificate);
- }
- }
-
- /**
- * Implementation of error handler for EventHandler.
- * Subclasses should call this method to have error fields set.
- * @param id The error id described by EventHandler.
- * @param description A string description of the error.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void error(int id, String description) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.error url:" +
- url() + " id:" + id + " description:" + description);
- }
- sendMessageInternal(obtainMessage(MSG_CONTENT_ERROR, id, 0, description));
- }
-
- // Handle the error on the WebCore thread.
- private void handleError(int id, String description) {
- mErrorID = id;
- mErrorDescription = description;
- detachRequestHandle();
- notifyError();
- tearDown();
- }
-
- /**
- * Add data to the internal collection of data. This function is used by
- * the data: scheme, about: scheme and http/https schemes.
- * @param data A byte array containing the content.
- * @param length The length of data.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- * XXX: Unlike the other network thread methods, this method can do the
- * work of decoding the data and appending it to the data builder.
- */
- public void data(byte[] data, int length) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.data(): url: " + url());
- }
-
- // The reason isEmpty() and append() need to synchronized together is
- // because it is possible for getFirstChunk() to be called multiple
- // times between isEmpty() and append(). This could cause commitLoad()
- // to finish before processing the newly appended data and no message
- // will be sent.
- boolean sendMessage = false;
- synchronized (mDataBuilder) {
- sendMessage = mDataBuilder.isEmpty();
- mDataBuilder.append(data, 0, length);
- }
- if (sendMessage) {
- // Send a message whenever data comes in after a write to WebCore
- sendMessageInternal(obtainMessage(MSG_CONTENT_DATA));
- }
- }
-
- /**
- * Event handler's endData call. Send a message to the handler notifying
- * them that the data has finished.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void endData() {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.endData(): url: " + url());
- }
- sendMessageInternal(obtainMessage(MSG_CONTENT_FINISHED));
- }
-
- // Handle the end of data.
- private void handleEndData() {
- if (mCancelled) return;
-
- switch (mStatusCode) {
- case HTTP_MOVED_PERMANENTLY:
- // 301 - permanent redirect
- mPermanent = true;
- case HTTP_FOUND:
- case HTTP_SEE_OTHER:
- case HTTP_TEMPORARY_REDIRECT:
- // 301, 302, 303, and 307 - redirect
- if (mStatusCode == HTTP_TEMPORARY_REDIRECT) {
- if (mRequestHandle != null &&
- mRequestHandle.getMethod().equals("POST")) {
- sendMessageInternal(obtainMessage(
- MSG_LOCATION_CHANGED_REQUEST));
- } else if (mMethod != null && mMethod.equals("POST")) {
- sendMessageInternal(obtainMessage(
- MSG_LOCATION_CHANGED_REQUEST));
- } else {
- sendMessageInternal(obtainMessage(MSG_LOCATION_CHANGED));
- }
- } else {
- sendMessageInternal(obtainMessage(MSG_LOCATION_CHANGED));
- }
- return;
-
- case HTTP_AUTH:
- case HTTP_PROXY_AUTH:
- // According to rfc2616, the response for HTTP_AUTH must include
- // WWW-Authenticate header field and the response for
- // HTTP_PROXY_AUTH must include Proxy-Authenticate header field.
- if (mAuthHeader != null &&
- (Network.getInstance(mContext).isValidProxySet() ||
- !mAuthHeader.isProxy())) {
- // If this is the first attempt to authenticate, try again with the username and
- // password supplied in the URL, if present.
- if (!mAuthFailed && mUsername != null && mPassword != null) {
- String host = mAuthHeader.isProxy() ?
- Network.getInstance(mContext).getProxyHostname() :
- mUri.getHost();
- HttpAuthHandlerImpl.onReceivedCredentials(this, host,
- mAuthHeader.getRealm(), mUsername, mPassword);
- makeAuthResponse(mUsername, mPassword);
- } else {
- Network.getInstance(mContext).handleAuthRequest(this);
- }
- return;
- }
- break; // use default
-
- case HTTP_NOT_MODIFIED:
- // Server could send back NOT_MODIFIED even if we didn't
- // ask for it, so make sure we have a valid CacheLoader
- // before calling it.
- if (mCacheLoader != null) {
- if (isSynchronous()) {
- mCacheLoader.load();
- } else {
- // Load the cached file in a separate thread
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER, mCacheLoader)
- .sendToTarget();
- }
- mFromCache = true;
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener cache load url=" + url());
- }
- return;
- }
- break; // use default
-
- case HTTP_NOT_FOUND:
- // Not an error, the server can send back content.
- default:
- break;
- }
- detachRequestHandle();
- tearDown();
- }
-
- /* This method is called from CacheLoader when the initial request is
- * serviced by the Cache. */
- /* package */ void setCacheLoader(CacheLoader c) {
- mCacheLoader = c;
- mFromCache = true;
- }
-
- /**
- * Check the cache for the current URL, and load it if it is valid.
- *
- * @param headers for the request
- * @return true if cached response is used.
- */
- boolean checkCache(Map<String, String> headers) {
- // Get the cache file name for the current URL
- CacheResult result = CacheManager.getCacheFile(url(), mPostIdentifier,
- headers);
-
- // Go ahead and set the cache loader to null in case the result is
- // null.
- mCacheLoader = null;
- // reset the flag
- mFromCache = false;
-
- if (result != null) {
- // The contents of the cache may need to be revalidated so just
- // remember the cache loader in the case that the server responds
- // positively to the cached content. This is also used to detect if
- // a redirect came from the cache.
- mCacheLoader = new CacheLoader(this, result);
-
- // If I got a cachedUrl and the revalidation header was not
- // added, then the cached content valid, we should use it.
- if (!headers.containsKey(
- CacheManager.HEADER_KEY_IFNONEMATCH) &&
- !headers.containsKey(
- CacheManager.HEADER_KEY_IFMODIFIEDSINCE)) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "FrameLoader: HTTP URL in cache " +
- "and usable: " + url());
- }
- if (isSynchronous()) {
- mCacheLoader.load();
- } else {
- // Load the cached file in a separate thread
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_ADD_STREAMLOADER, mCacheLoader)
- .sendToTarget();
- }
- mFromCache = true;
- return true;
- }
- }
- return false;
- }
-
- /**
- * SSL certificate error callback. Handles SSL error(s) on the way up
- * to the user.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public boolean handleSslErrorRequest(SslError error) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG,
- "LoadListener.handleSslErrorRequest(): url:" + url() +
- " primary error: " + error.getPrimaryError() +
- " certificate: " + error.getCertificate());
- }
- // Check the cached preference table before sending a message. This
- // will prevent waiting for an already available answer.
- if (Network.getInstance(mContext).checkSslPrefTable(this, error)) {
- return true;
- }
- // Do not post a message for a synchronous request. This will cause a
- // deadlock. Just bail on the request.
- if (isSynchronous()) {
- mRequestHandle.handleSslErrorResponse(false);
- return true;
- }
- sendMessageInternal(obtainMessage(MSG_SSL_ERROR, error));
- // if it has been canceled, return false so that the network thread
- // won't be blocked. If it is not canceled, save the mRequestHandle
- // so that if it is canceled when MSG_SSL_ERROR is handled, we can
- // still call handleSslErrorResponse which will call restartConnection
- // to unblock the network thread.
- if (!mCancelled) {
- mSslErrorRequestHandle = mRequestHandle;
- }
- return !mCancelled;
- }
-
- // Handle the ssl error on the WebCore thread.
- private void handleSslError(SslError error) {
- if (!mCancelled) {
- mSslError = error;
- Network.getInstance(mContext).handleSslErrorRequest(this);
- } else if (mSslErrorRequestHandle != null) {
- mSslErrorRequestHandle.handleSslErrorResponse(true);
- }
- mSslErrorRequestHandle = null;
- }
-
- /**
- * @return HTTP authentication realm or null if none.
- */
- String realm() {
- if (mAuthHeader == null) {
- return null;
- } else {
- return mAuthHeader.getRealm();
- }
- }
-
- /**
- * Returns true iff an HTTP authentication problem has
- * occured (credentials invalid).
- */
- boolean authCredentialsInvalid() {
- // if it is digest and the nonce is stale, we just
- // resubmit with a new nonce
- return (mAuthFailed &&
- !(mAuthHeader.isDigest() && mAuthHeader.getStale()));
- }
-
- /**
- * @return The last SSL error or null if there is none
- */
- SslError sslError() {
- return mSslError;
- }
-
- /**
- * Handles SSL error(s) on the way down from the user
- * (the user has already provided their feedback).
- */
- void handleSslErrorResponse(boolean proceed) {
- if (mRequestHandle != null) {
- mRequestHandle.handleSslErrorResponse(proceed);
- }
- if (!proceed) {
- mBrowserFrame.stopLoading();
- tearDown();
- }
- }
-
- /**
- * Uses user-supplied credentials to restart a request. If the credentials
- * are null, cancel the request.
- */
- void handleAuthResponse(String username, String password) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.handleAuthResponse: url: " + mUrl
- + " username: " + username
- + " password: " + password);
- }
- if (username != null && password != null) {
- makeAuthResponse(username, password);
- } else {
- // Commit whatever data we have and tear down the loader.
- commitLoad();
- tearDown();
- }
- }
-
- void makeAuthResponse(String username, String password) {
- if (mAuthHeader == null || mRequestHandle == null) {
- return;
- }
-
- mAuthHeader.setUsername(username);
- mAuthHeader.setPassword(password);
-
- int scheme = mAuthHeader.getScheme();
- if (scheme == HttpAuthHeader.BASIC) {
- // create a basic response
- boolean isProxy = mAuthHeader.isProxy();
-
- mRequestHandle.setupBasicAuthResponse(isProxy, username, password);
- } else if (scheme == HttpAuthHeader.DIGEST) {
- // create a digest response
- boolean isProxy = mAuthHeader.isProxy();
-
- String realm = mAuthHeader.getRealm();
- String nonce = mAuthHeader.getNonce();
- String qop = mAuthHeader.getQop();
- String algorithm = mAuthHeader.getAlgorithm();
- String opaque = mAuthHeader.getOpaque();
-
- mRequestHandle.setupDigestAuthResponse(isProxy, username, password,
- realm, nonce, qop, algorithm, opaque);
- }
- }
-
- /**
- * This is called when a request can be satisfied by the cache, however,
- * the cache result could be a redirect. In this case we need to issue
- * the network request.
- * @param method
- * @param headers
- * @param postData
- */
- void setRequestData(String method, Map<String, String> headers,
- byte[] postData) {
- mMethod = method;
- mRequestHeaders = headers;
- mPostData = postData;
- }
-
- /**
- * @return The current URL associated with this load.
- */
- String url() {
- return mUrl;
- }
-
- /**
- * @return The current WebAddress associated with this load.
- */
- WebAddress getWebAddress() {
- return mUri;
- }
-
- /**
- * @return URL hostname (current URL).
- */
- String host() {
- if (mUri != null) {
- return mUri.getHost();
- }
-
- return null;
- }
-
- /**
- * @return The original URL associated with this load.
- */
- String originalUrl() {
- if (mOriginalUrl != null) {
- return mOriginalUrl;
- } else {
- return mUrl;
- }
- }
-
- long postIdentifier() {
- return mPostIdentifier;
- }
-
- void attachRequestHandle(RequestHandle requestHandle) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.attachRequestHandle(): " +
- "requestHandle: " + requestHandle);
- }
- mRequestHandle = requestHandle;
- }
-
- void detachRequestHandle() {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.detachRequestHandle(): " +
- "requestHandle: " + mRequestHandle);
- }
- mRequestHandle = null;
- }
-
- /*
- * This function is called from native WebCore code to
- * notify this LoadListener that the content it is currently
- * downloading should be saved to a file and not sent to
- * WebCore.
- */
- void downloadFile() {
- // remove the cache
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
-
- // Inform the client that they should download a file
- mBrowserFrame.getCallbackProxy().onDownloadStart(url(),
- mBrowserFrame.getUserAgentString(),
- mHeaders.getContentDisposition(),
- mMimeType, mContentLength);
-
- // Cancel the download. We need to stop the http load.
- // The native loader object will get cleared by the call to
- // cancel() but will also be cleared on the WebCore side
- // when this function returns.
- cancel();
- }
-
- /*
- * This function is called from native WebCore code to
- * find out if the given URL is in the cache, and if it can
- * be used. This is just for forward/back navigation to a POST
- * URL.
- */
- private static boolean willLoadFromCache(String url, long identifier) {
- assert !JniUtil.useChromiumHttpStack();
- boolean inCache =
- CacheManager.getCacheFile(url, identifier, null) != null;
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "willLoadFromCache: " + url + " in cache: " +
- inCache);
- }
- return inCache;
- }
-
- /*
- * Reset the cancel flag. This is used when we are resuming a stopped
- * download. To suspend a download, we cancel it. It can also be cancelled
- * when it has run out of disk space. In this situation, the download
- * can be resumed.
- */
- void resetCancel() {
- mCancelled = false;
- }
-
- String mimeType() {
- return mMimeType;
- }
-
- String transferEncoding() {
- return mTransferEncoding;
- }
-
- /*
- * Return the size of the content being downloaded. This represents the
- * full content size, even under the situation where the download has been
- * resumed after interruption.
- *
- * @ return full content size
- */
- long contentLength() {
- return mContentLength;
- }
-
- // Commit the headers if the status code is not a redirect.
- private void commitHeadersCheckRedirect() {
- if (mCancelled) return;
-
- // do not call webcore if it is redirect. According to the code in
- // InspectorController::willSendRequest(), the response is only updated
- // when it is not redirect. If we received a not-modified response from
- // the server and mCacheLoader is not null, do not send the response to
- // webkit. This is just a validation response for loading from the
- // cache.
- if ((mStatusCode >= 301 && mStatusCode <= 303) || mStatusCode == 307 ||
- (mStatusCode == 304 && mCacheLoader != null)) {
- return;
- }
-
- commitHeaders();
- }
-
- // This commits the headers without checking the response status code.
- private void commitHeaders() {
- if (mIsMainPageLoader && CertTool.getCertType(mMimeType) != null) {
- // In the case of downloading certificate, we will save it to the
- // KeyStore in commitLoad. Do not call webcore.
- return;
- }
-
- // If the response is an authentication and we've resent the
- // request with some credentials then don't commit the headers
- // of this response; wait for the response to the request with the
- // credentials.
- if (mAuthHeader != null) {
- return;
- }
-
- setNativeResponse();
- }
-
- private void setNativeResponse() {
- int nativeResponse = createNativeResponse();
- // The native code deletes the native response object.
- nativeReceivedResponse(nativeResponse);
- mSetNativeResponse = true;
- }
-
- /**
- * Create a WebCore response object so that it can be used by
- * nativeReceivedResponse or nativeRedirectedToUrl
- * @return native response pointer
- */
- private int createNativeResponse() {
- // If WebCore sends if-modified-since, mCacheLoader is null. If
- // CacheManager sends it, mCacheLoader is not null. In this case, if the
- // server responds with a 304, then we treat it like it was a 200 code
- // and proceed with loading the file from the cache.
- int statusCode = (mStatusCode == HTTP_NOT_MODIFIED &&
- mCacheLoader != null) ? HTTP_OK : mStatusCode;
- // pass content-type content-length and content-encoding
- final int nativeResponse = nativeCreateResponse(
- originalUrl(), statusCode, mStatusText,
- mMimeType, mContentLength, mEncoding);
- if (mHeaders != null) {
- mHeaders.getHeaders(new Headers.HeaderCallback() {
- public void header(String name, String value) {
- nativeSetResponseHeader(nativeResponse, name, value);
- }
- });
- }
- return nativeResponse;
- }
-
- /**
- * Commit the load. It should be ok to call repeatedly but only before
- * tearDown is called.
- */
- private void commitLoad() {
- if (mCancelled) return;
- if (!mSetNativeResponse) {
- setNativeResponse();
- }
-
- if (mIsMainPageLoader) {
- String type = CertTool.getCertType(mMimeType);
- if (type != null) {
- // This must be synchronized so that no more data can be added
- // after getByteSize returns.
- synchronized (mDataBuilder) {
- // In the case of downloading certificate, we will save it
- // to the KeyStore and stop the current loading so that it
- // will not generate a new history page
- byte[] cert = new byte[mDataBuilder.getByteSize()];
- int offset = 0;
- while (true) {
- ByteArrayBuilder.Chunk c = mDataBuilder.getFirstChunk();
- if (c == null) break;
-
- if (c.mLength != 0) {
- System.arraycopy(c.mArray, 0, cert, offset, c.mLength);
- offset += c.mLength;
- }
- c.release();
- }
- CertTool.addCertificate(mContext, type, cert);
- mBrowserFrame.stopLoading();
- return;
- }
- }
- }
-
- // Give the data to WebKit now. We don't have to synchronize on
- // mDataBuilder here because pulling each chunk removes it from the
- // internal list so it cannot be modified.
- ByteArrayBuilder.Chunk c;
- while (true) {
- c = mDataBuilder.getFirstChunk();
- if (c == null) break;
-
- if (c.mLength != 0) {
- nativeAddData(c.mArray, c.mLength);
- WebViewWorker.CacheData data = new WebViewWorker.CacheData();
- data.mListener = this;
- data.mChunk = c;
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_APPEND_CACHE, data).sendToTarget();
- } else {
- c.release();
- }
- }
- }
-
- /**
- * Tear down the load. Subclasses should clean up any mess because of
- * cancellation or errors during the load.
- */
- void tearDown() {
- if (getErrorID() == OK) {
- WebViewWorker.CacheSaveData data = new WebViewWorker.CacheSaveData();
- data.mListener = this;
- data.mUrl = mUrl;
- data.mPostId = mPostIdentifier;
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_SAVE_CACHE, data).sendToTarget();
- } else {
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
- }
- if (mNativeLoader != 0) {
- if (!mSetNativeResponse) {
- setNativeResponse();
- }
-
- nativeFinished();
- clearNativeLoader();
- }
- }
-
- /**
- * Helper for getting the error ID.
- * @return errorID.
- */
- private int getErrorID() {
- return mErrorID;
- }
-
- /**
- * Return the error description.
- * @return errorDescription.
- */
- private String getErrorDescription() {
- return mErrorDescription;
- }
-
- /**
- * Notify the loader we encountered an error.
- */
- void notifyError() {
- if (mNativeLoader != 0) {
- String description = getErrorDescription();
- if (description == null) description = "";
- nativeError(getErrorID(), description, url());
- clearNativeLoader();
- }
- }
-
- /**
- * Pause the load. For example, if a plugin is unable to accept more data,
- * we pause reading from the request. Called directly from the WebCore thread.
- */
- void pauseLoad(boolean pause) {
- if (mRequestHandle != null) {
- mRequestHandle.pauseRequest(pause);
- }
- }
-
- /**
- * Cancel a request.
- * FIXME: This will only work if the request has yet to be handled. This
- * is in no way guarenteed if requests are served in a separate thread.
- * It also causes major problems if cancel is called during an
- * EventHandler's method call.
- */
- public void cancel() {
- if (DebugFlags.LOAD_LISTENER) {
- if (mRequestHandle == null) {
- Log.v(LOGTAG, "LoadListener.cancel(): no requestHandle");
- } else {
- Log.v(LOGTAG, "LoadListener.cancel()");
- }
- }
- if (mRequestHandle != null) {
- mRequestHandle.cancel();
- mRequestHandle = null;
- }
-
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
- mCancelled = true;
-
- clearNativeLoader();
- }
-
- // This count is transferred from RequestHandle to LoadListener when
- // loading from the cache so that we can detect redirect loops that switch
- // between the network and the cache.
- private int mCacheRedirectCount;
-
- /*
- * Perform the actual redirection. This involves setting up the new URL,
- * informing WebCore and then telling the Network to start loading again.
- */
- private void doRedirect() {
- // as cancel() can cancel the load before doRedirect() is
- // called through handleMessage, needs to check to see if we
- // are canceled before proceed
- if (mCancelled) {
- return;
- }
-
- // Do the same check for a redirect loop that
- // RequestHandle.setupRedirect does.
- if (mCacheRedirectCount >= RequestHandle.MAX_REDIRECT_COUNT) {
- handleError(EventHandler.ERROR_REDIRECT_LOOP, mContext.getString(
- R.string.httpErrorRedirectLoop));
- return;
- }
-
- String redirectTo = mHeaders.getLocation();
- if (redirectTo != null) {
- int nativeResponse = createNativeResponse();
- redirectTo =
- nativeRedirectedToUrl(mUrl, redirectTo, nativeResponse);
- // nativeRedirectedToUrl() may call cancel(), e.g. when redirect
- // from a https site to a http site, check mCancelled again
- if (mCancelled) {
- return;
- }
- if (redirectTo == null) {
- Log.d(LOGTAG, "Redirection failed for "
- + mHeaders.getLocation());
- cancel();
- return;
- } else if (!URLUtil.isNetworkUrl(redirectTo)) {
- final String text = mContext
- .getString(R.string.open_permission_deny)
- + "\n" + redirectTo;
- if (!mSetNativeResponse) {
- setNativeResponse();
- }
- nativeAddData(text.getBytes(), text.length());
- nativeFinished();
- clearNativeLoader();
- return;
- }
-
-
- // Cache the redirect response
- if (getErrorID() == OK) {
- WebViewWorker.CacheSaveData data = new WebViewWorker.CacheSaveData();
- data.mListener = this;
- data.mUrl = mUrl;
- data.mPostId = mPostIdentifier;
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_SAVE_CACHE, data).sendToTarget();
- } else {
- WebViewWorker.getHandler().obtainMessage(
- WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
- }
-
- // Saving a copy of the unstripped url for the response
- mOriginalUrl = redirectTo;
- // This will strip the anchor
- setUrl(redirectTo);
-
- // Redirect may be in the cache
- if (mRequestHeaders == null) {
- mRequestHeaders = new HashMap<String, String>();
- }
- boolean fromCache = false;
- if (mCacheLoader != null) {
- // This is a redirect from the cache loader. Increment the
- // redirect count to avoid redirect loops.
- mCacheRedirectCount++;
- fromCache = true;
- }
- if (!checkCache(mRequestHeaders)) {
- // mRequestHandle can be null when the request was satisfied
- // by the cache, and the cache returned a redirect
- if (mRequestHandle != null) {
- try {
- mRequestHandle.setupRedirect(mUrl, mStatusCode,
- mRequestHeaders);
- } catch(RuntimeException e) {
- Log.e(LOGTAG, e.getMessage());
- // Signal a bad url error if we could not load the
- // redirection.
- handleError(EventHandler.ERROR_BAD_URL,
- mContext.getString(R.string.httpErrorBadUrl));
- return;
- }
- } else {
- // If the original request came from the cache, there is no
- // RequestHandle, we have to create a new one through
- // Network.requestURL.
- Network network = Network.getInstance(getContext());
- if (!network.requestURL(mMethod, mRequestHeaders,
- mPostData, this)) {
- // Signal a bad url error if we could not load the
- // redirection.
- handleError(EventHandler.ERROR_BAD_URL,
- mContext.getString(R.string.httpErrorBadUrl));
- return;
- }
- }
- if (fromCache) {
- // If we are coming from a cache load, we need to transfer
- // the redirect count to the new (or old) RequestHandle to
- // keep the redirect count in sync.
- mRequestHandle.setRedirectCount(mCacheRedirectCount);
- }
- } else if (!fromCache) {
- // Switching from network to cache means we need to grab the
- // redirect count from the RequestHandle to keep the count in
- // sync. Add 1 to account for the current redirect.
- mCacheRedirectCount = mRequestHandle.getRedirectCount() + 1;
- }
- } else {
- commitHeaders();
- commitLoad();
- tearDown();
- }
-
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.onRedirect(): redirect to: " +
- redirectTo);
- }
- }
-
- /**
- * Parses the content-type header.
- * The first part only allows '-' if it follows x or X.
- */
- private static final Pattern CONTENT_TYPE_PATTERN =
- Pattern.compile("^((?:[xX]-)?[a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$");
-
- /* package */ void parseContentTypeHeader(String contentType) {
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "LoadListener.parseContentTypeHeader: " +
- "contentType: " + contentType);
- }
-
- if (contentType != null) {
- int i = contentType.indexOf(';');
- if (i >= 0) {
- mMimeType = contentType.substring(0, i);
-
- int j = contentType.indexOf('=', i);
- if (j > 0) {
- i = contentType.indexOf(';', j);
- if (i < j) {
- i = contentType.length();
- }
- mEncoding = contentType.substring(j + 1, i);
- } else {
- mEncoding = contentType.substring(i + 1);
- }
- // Trim excess whitespace.
- mEncoding = mEncoding.trim().toLowerCase();
-
- if (i < contentType.length() - 1) {
- // for data: uri the mimeType and encoding have
- // the form image/jpeg;base64 or text/plain;charset=utf-8
- // or text/html;charset=utf-8;base64
- mTransferEncoding =
- contentType.substring(i + 1).trim().toLowerCase();
- }
- } else {
- mMimeType = contentType;
- }
-
- // Trim leading and trailing whitespace
- mMimeType = mMimeType.trim();
-
- try {
- Matcher m = CONTENT_TYPE_PATTERN.matcher(mMimeType);
- if (m.find()) {
- mMimeType = m.group(1);
- } else {
- guessMimeType();
- }
- } catch (IllegalStateException ex) {
- guessMimeType();
- }
- }
- // Ensure mMimeType is lower case.
- mMimeType = mMimeType.toLowerCase();
- }
-
- /**
- * @return The HTTP-authentication object or null if there
- * is no supported scheme in the header.
- * If there are several valid schemes present, we pick the
- * strongest one. If there are several schemes of the same
- * strength, we pick the one that comes first.
- */
- private HttpAuthHeader parseAuthHeader(String header) {
- if (header != null) {
- int posMax = 256;
- int posLen = 0;
- int[] pos = new int [posMax];
-
- int headerLen = header.length();
- if (headerLen > 0) {
- // first, we find all unquoted instances of 'Basic' and 'Digest'
- boolean quoted = false;
- for (int i = 0; i < headerLen && posLen < posMax; ++i) {
- if (header.charAt(i) == '\"') {
- quoted = !quoted;
- } else {
- if (!quoted) {
- if (header.regionMatches(true, i,
- HttpAuthHeader.BASIC_TOKEN, 0,
- HttpAuthHeader.BASIC_TOKEN.length())) {
- pos[posLen++] = i;
- continue;
- }
-
- if (header.regionMatches(true, i,
- HttpAuthHeader.DIGEST_TOKEN, 0,
- HttpAuthHeader.DIGEST_TOKEN.length())) {
- pos[posLen++] = i;
- continue;
- }
- }
- }
- }
- }
-
- if (posLen > 0) {
- // consider all digest schemes first (if any)
- for (int i = 0; i < posLen; i++) {
- if (header.regionMatches(true, pos[i],
- HttpAuthHeader.DIGEST_TOKEN, 0,
- HttpAuthHeader.DIGEST_TOKEN.length())) {
- String sub = header.substring(pos[i],
- (i + 1 < posLen ? pos[i + 1] : headerLen));
-
- HttpAuthHeader rval = new HttpAuthHeader(sub);
- if (rval.isSupportedScheme()) {
- // take the first match
- return rval;
- }
- }
- }
-
- // ...then consider all basic schemes (if any)
- for (int i = 0; i < posLen; i++) {
- if (header.regionMatches(true, pos[i],
- HttpAuthHeader.BASIC_TOKEN, 0,
- HttpAuthHeader.BASIC_TOKEN.length())) {
- String sub = header.substring(pos[i],
- (i + 1 < posLen ? pos[i + 1] : headerLen));
-
- HttpAuthHeader rval = new HttpAuthHeader(sub);
- if (rval.isSupportedScheme()) {
- // take the first match
- return rval;
- }
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * If the content is a redirect or not modified we should not send
- * any data into WebCore as that will cause it create a document with
- * the data, then when we try to provide the real content, it will assert.
- *
- * @return True iff the callback should be ignored.
- */
- private boolean ignoreCallbacks() {
- return (mCancelled || mAuthHeader != null ||
- // Allow 305 (Use Proxy) to call through.
- (mStatusCode > 300 && mStatusCode < 400 && mStatusCode != 305));
- }
-
- /**
- * Sets the current URL associated with this load.
- */
- void setUrl(String url) {
- if (url != null) {
- mUri = null;
- if (URLUtil.isNetworkUrl(url)) {
- mUrl = URLUtil.stripAnchor(url);
- try {
- mUri = new WebAddress(mUrl);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- } else {
- mUrl = url;
- }
- }
- }
-
- /**
- * Guesses MIME type if one was not specified. Defaults to 'text/html'. In
- * addition, tries to guess the MIME type based on the extension.
- *
- */
- private void guessMimeType() {
- // Data urls must have a valid mime type or a blank string for the mime
- // type (implying text/plain).
- if (URLUtil.isDataUrl(mUrl) && mMimeType.length() != 0) {
- cancel();
- final String text = mContext.getString(R.string.httpErrorBadUrl);
- handleError(EventHandler.ERROR_BAD_URL, text);
- } else {
- // Note: This is ok because this is used only for the main content
- // of frames. If no content-type was specified, it is fine to
- // default to text/html.
- mMimeType = "text/html";
- String newMimeType = guessMimeTypeFromExtension(mUrl);
- if (newMimeType != null) {
- mMimeType = newMimeType;
- }
- }
- }
-
- /**
- * guess MIME type based on the file extension.
- */
- private String guessMimeTypeFromExtension(String url) {
- // PENDING: need to normalize url
- if (DebugFlags.LOAD_LISTENER) {
- Log.v(LOGTAG, "guessMimeTypeFromExtension: url = " + url);
- }
-
- return MimeTypeMap.getSingleton().getMimeTypeFromExtension(
- MimeTypeMap.getFileExtensionFromUrl(url));
- }
-
- /**
- * Either send a message to ourselves or queue the message if this is a
- * synchronous load.
- */
- private void sendMessageInternal(Message msg) {
- if (mSynchronous) {
- mMessageQueue.add(msg);
- } else {
- sendMessage(msg);
- }
- }
-
- /**
- * Cycle through our messages for synchronous loads.
- */
- /* package */ void loadSynchronousMessages() {
- if (DebugFlags.LOAD_LISTENER && !mSynchronous) {
- throw new AssertionError();
- }
- // Note: this can be called twice if it is a synchronous network load,
- // and there is a cache, but it needs to go to network to validate. If
- // validation succeed, the CacheLoader is used so this is first called
- // from http thread. Then it is called again from WebViewCore thread
- // after the load is completed. So make sure the queue is cleared but
- // don't set it to null.
- while (!mMessageQueue.isEmpty()) {
- handleMessage(mMessageQueue.remove(0));
- }
- }
-
- //=========================================================================
- // native functions
- //=========================================================================
-
- /**
- * Create a new native response object.
- * @param url The url of the resource.
- * @param statusCode The HTTP status code.
- * @param statusText The HTTP status text.
- * @param mimeType HTTP content-type.
- * @param expectedLength An estimate of the content length or the length
- * given by the server.
- * @param encoding HTTP encoding.
- * @return The native response pointer.
- */
- private native int nativeCreateResponse(String url, int statusCode,
- String statusText, String mimeType, long expectedLength,
- String encoding);
-
- /**
- * Add a response header to the native object.
- * @param nativeResponse The native pointer.
- * @param key String key.
- * @param val String value.
- */
- private native void nativeSetResponseHeader(int nativeResponse, String key,
- String val);
-
- /**
- * Dispatch the response.
- * @param nativeResponse The native pointer.
- */
- private native void nativeReceivedResponse(int nativeResponse);
-
- /**
- * Add data to the loader.
- * @param data Byte array of data.
- * @param length Number of objects in data.
- */
- private native void nativeAddData(byte[] data, int length);
-
- /**
- * Tell the loader it has finished.
- */
- private native void nativeFinished();
-
- /**
- * tell the loader to redirect
- * @param baseUrl The base url.
- * @param redirectTo The url to redirect to.
- * @param nativeResponse The native pointer.
- * @return The new url that the resource redirected to.
- */
- private native String nativeRedirectedToUrl(String baseUrl,
- String redirectTo, int nativeResponse);
-
- /**
- * Tell the loader there is error
- * @param id
- * @param desc
- * @param failingUrl The url that failed.
- */
- private native void nativeError(int id, String desc, String failingUrl);
-
-}
diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java
deleted file mode 100644
index ee9b949..0000000
--- a/core/java/android/webkit/Network.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.http.*;
-import android.os.*;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.Map;
-
-import junit.framework.Assert;
-
-class Network {
-
- private static final String LOGTAG = "network";
-
- /**
- * Static instance of a Network object.
- */
- private static Network sNetwork;
-
- /**
- * Flag to store the state of platform notifications, for the case
- * when the Network object has not been constructed yet
- */
- private static boolean sPlatformNotifications;
-
- /**
- * Reference count for platform notifications as the network class is a
- * static and can exist over multiple activities, thus over multiple
- * onPause/onResume pairs.
- */
- private static int sPlatformNotificationEnableRefCount;
-
- /**
- * Proxy username if known (used for pre-emptive proxy authentication).
- */
- private String mProxyUsername;
-
- /**
- * Proxy password if known (used for pre-emptive proxy authentication).
- */
- private String mProxyPassword;
-
- /**
- * Network request queue (requests are added from the browser thread).
- */
- private RequestQueue mRequestQueue;
-
- /**
- * SSL error handler: takes care of synchronization of multiple async
- * loaders with SSL-related problems.
- */
- private SslErrorHandlerImpl mSslErrorHandler;
-
- /**
- * HTTP authentication handler: takes care of synchronization of HTTP
- * authentication requests.
- */
- private HttpAuthHandlerImpl mHttpAuthHandler;
-
- private Context mContext;
-
- /**
- * True if the currently used network connection is a roaming phone
- * connection.
- */
- private boolean mRoaming;
-
- /**
- * Tracks if we are roaming.
- */
- private RoamingMonitor mRoamingMonitor;
-
- /**
- * @return The singleton instance of the network.
- */
- public static synchronized Network getInstance(Context context) {
- if (sNetwork == null) {
- // Note Context of the Application is used here, rather than
- // the what is passed in (usually a Context derived from an
- // Activity) so the intent receivers belong to the application
- // rather than an activity - this fixes the issue where
- // Activities are created and destroyed during the lifetime of
- // an Application
- sNetwork = new Network(context.getApplicationContext());
- if (sPlatformNotifications) {
- // Adjust the ref count before calling enable as it is already
- // taken into account when the static function was called
- // directly
- --sPlatformNotificationEnableRefCount;
- enablePlatformNotifications();
- }
- }
- return sNetwork;
- }
-
-
- /**
- * Enables data state and proxy tracking
- */
- public static void enablePlatformNotifications() {
- if (++sPlatformNotificationEnableRefCount == 1) {
- if (sNetwork != null) {
- sNetwork.mRequestQueue.enablePlatformNotifications();
- sNetwork.monitorRoaming();
- } else {
- sPlatformNotifications = true;
- }
- }
- }
-
- /**
- * If platform notifications are enabled, this should be called
- * from onPause() or onStop()
- */
- public static void disablePlatformNotifications() {
- if (--sPlatformNotificationEnableRefCount == 0) {
- if (sNetwork != null) {
- sNetwork.mRequestQueue.disablePlatformNotifications();
- sNetwork.stopMonitoringRoaming();
- } else {
- sPlatformNotifications = false;
- }
- }
- }
-
- /**
- * Creates a new Network object.
- * XXX: Must be created in the same thread as WebCore!!!!!
- */
- private Network(Context context) {
- if (DebugFlags.NETWORK) {
- Assert.assertTrue(Thread.currentThread().
- getName().equals(WebViewCore.THREAD_NAME));
- }
- mContext = context;
- mSslErrorHandler = new SslErrorHandlerImpl();
- mHttpAuthHandler = new HttpAuthHandlerImpl(this);
-
- mRequestQueue = new RequestQueue(context);
- }
-
- private class RoamingMonitor extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
- return;
-
- final ConnectivityManager connManager = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- final NetworkInfo info = connManager.getActiveNetworkInfo();
- if (info != null)
- mRoaming = info.isRoaming();
- };
- };
-
- private void monitorRoaming() {
- mRoamingMonitor = new RoamingMonitor();
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(sNetwork.mRoamingMonitor, filter);
- }
-
- private void stopMonitoringRoaming() {
- if (mRoamingMonitor != null) {
- mContext.unregisterReceiver(mRoamingMonitor);
- mRoamingMonitor = null;
- }
- }
-
- /**
- * Request a url from either the network or the file system.
- * @param url The url to load.
- * @param method The http method.
- * @param headers The http headers.
- * @param postData The body of the request.
- * @param loader A LoadListener for receiving the results of the request.
- * @return True if the request was successfully queued.
- */
- public boolean requestURL(String method,
- Map<String, String> headers,
- byte [] postData,
- LoadListener loader) {
-
- String url = loader.url();
-
- // Not a valid url, return false because we won't service the request!
- if (!URLUtil.isValidUrl(url)) {
- return false;
- }
-
- // asset, res, file system or data stream are handled in the other code
- // path. This only handles network request.
- if (URLUtil.isAssetUrl(url) || URLUtil.isResourceUrl(url)
- || URLUtil.isFileUrl(url) || URLUtil.isDataUrl(url)) {
- return false;
- }
-
- // If this is a prefetch, abort it if we're roaming.
- if (mRoaming && headers.containsKey("X-Moz") && "prefetch".equals(headers.get("X-Moz"))) {
- return false;
- }
-
- /* FIXME: this is lame. Pass an InputStream in, rather than
- making this lame one here */
- InputStream bodyProvider = null;
- int bodyLength = 0;
- if (postData != null) {
- bodyLength = postData.length;
- bodyProvider = new ByteArrayInputStream(postData);
- }
-
- RequestQueue q = mRequestQueue;
- RequestHandle handle = null;
- if (loader.isSynchronous()) {
- handle = q.queueSynchronousRequest(url, loader.getWebAddress(),
- method, headers, loader, bodyProvider, bodyLength);
- loader.attachRequestHandle(handle);
- handle.processRequest();
- loader.loadSynchronousMessages();
- } else {
- handle = q.queueRequest(url, loader.getWebAddress(), method,
- headers, loader, bodyProvider, bodyLength);
- // FIXME: Although this is probably a rare condition, normal network
- // requests are processed in a separate thread. This means that it
- // is possible to process part of the request before setting the
- // request handle on the loader. We should probably refactor this to
- // ensure the handle is attached before processing begins.
- loader.attachRequestHandle(handle);
- }
-
- return true;
- }
-
- /**
- * @return True iff there is a valid proxy set.
- */
- public boolean isValidProxySet() {
- // The proxy host and port can be set within a different thread during
- // an Intent broadcast.
- synchronized (mRequestQueue) {
- return mRequestQueue.getProxyHost() != null;
- }
- }
-
- /**
- * Get the proxy hostname.
- * @return The proxy hostname obtained from the network queue and proxy
- * settings.
- */
- public String getProxyHostname() {
- return mRequestQueue.getProxyHost().getHostName();
- }
-
- /**
- * @return The proxy username or null if none.
- */
- public synchronized String getProxyUsername() {
- return mProxyUsername;
- }
-
- /**
- * Sets the proxy username.
- * @param proxyUsername Username to use when
- * connecting through the proxy.
- */
- public synchronized void setProxyUsername(String proxyUsername) {
- if (DebugFlags.NETWORK) {
- Assert.assertTrue(isValidProxySet());
- }
-
- mProxyUsername = proxyUsername;
- }
-
- /**
- * @return The proxy password or null if none.
- */
- public synchronized String getProxyPassword() {
- return mProxyPassword;
- }
-
- /**
- * Sets the proxy password.
- * @param proxyPassword Password to use when
- * connecting through the proxy.
- */
- public synchronized void setProxyPassword(String proxyPassword) {
- if (DebugFlags.NETWORK) {
- Assert.assertTrue(isValidProxySet());
- }
-
- mProxyPassword = proxyPassword;
- }
-
- /**
- * Saves the state of network handlers (user SSL and HTTP-authentication
- * preferences).
- * @param outState The out-state to save (write) to.
- * @return True iff succeeds.
- */
- public boolean saveState(Bundle outState) {
- if (DebugFlags.NETWORK) {
- Log.v(LOGTAG, "Network.saveState()");
- }
-
- return mSslErrorHandler.saveState(outState);
- }
-
- /**
- * Restores the state of network handlers (user SSL and HTTP-authentication
- * preferences).
- * @param inState The in-state to load (read) from.
- * @return True iff succeeds.
- */
- public boolean restoreState(Bundle inState) {
- if (DebugFlags.NETWORK) {
- Log.v(LOGTAG, "Network.restoreState()");
- }
-
- return mSslErrorHandler.restoreState(inState);
- }
-
- /**
- * Clears user SSL-error preference table.
- */
- public void clearUserSslPrefTable() {
- mSslErrorHandler.clear();
- }
-
- /**
- * Handles SSL error(s) on the way up to the user: the user must decide
- * whether errors should be ignored or not.
- * @param loader The loader that resulted in SSL errors.
- */
- public void handleSslErrorRequest(LoadListener loader) {
- if (DebugFlags.NETWORK) Assert.assertNotNull(loader);
- if (loader != null) {
- mSslErrorHandler.handleSslErrorRequest(loader);
- }
- }
-
- /* package */ boolean checkSslPrefTable(LoadListener loader,
- SslError error) {
- if (loader != null && error != null) {
- return mSslErrorHandler.checkSslPrefTable(loader, error);
- }
- return false;
- }
-
- /**
- * Handles authentication requests on their way up to the user (the user
- * must provide credentials).
- * @param loader The loader that resulted in an HTTP
- * authentication request.
- */
- public void handleAuthRequest(LoadListener loader) {
- if (DebugFlags.NETWORK) Assert.assertNotNull(loader);
- if (loader != null) {
- mHttpAuthHandler.handleAuthRequest(loader);
- }
- }
-
- // Performance probe
- public void startTiming() {
- mRequestQueue.startTiming();
- }
-
- public void stopTiming() {
- mRequestQueue.stopTiming();
- }
-}
diff --git a/core/java/android/webkit/SslErrorHandlerImpl.java b/core/java/android/webkit/SslErrorHandlerImpl.java
deleted file mode 100644
index b2e4b13..0000000
--- a/core/java/android/webkit/SslErrorHandlerImpl.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.SslError;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * SslErrorHandler's implementation for Android Java HTTP stack.
- * This class is not needed if the Chromium HTTP stack is used.
- */
-class SslErrorHandlerImpl extends SslErrorHandler {
- /* One problem here is that there may potentially be multiple SSL errors
- * coming from multiple loaders. Therefore, we keep a queue of loaders
- * that have SSL-related problems and process errors one by one in the
- * order they were received.
- */
-
- private static final String LOGTAG = "network";
-
- /**
- * Queue of loaders that experience SSL-related problems.
- */
- private LinkedList<LoadListener> mLoaderQueue;
-
- /**
- * SSL error preference table.
- */
- private Bundle mSslPrefTable;
-
- // These are only used in the client facing SslErrorHandler.
- private final SslErrorHandler mOriginHandler;
- private final LoadListener mLoadListener;
-
- // Message id for handling the response from the client.
- private static final int HANDLE_RESPONSE = 100;
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case HANDLE_RESPONSE:
- LoadListener loader = (LoadListener) msg.obj;
- synchronized (SslErrorHandlerImpl.this) {
- handleSslErrorResponse(loader, loader.sslError(),
- msg.arg1 == 1);
- mLoaderQueue.remove(loader);
- fastProcessQueuedSslErrors();
- }
- break;
- }
- }
-
- /**
- * Creates a new error handler with an empty loader queue.
- */
- /* package */ SslErrorHandlerImpl() {
- mLoaderQueue = new LinkedList<LoadListener>();
- mSslPrefTable = new Bundle();
-
- // These are used by client facing SslErrorHandlers.
- mOriginHandler = null;
- mLoadListener = null;
- }
-
- /**
- * Create a new error handler that will be passed to the client.
- */
- private SslErrorHandlerImpl(SslErrorHandler origin, LoadListener listener) {
- mOriginHandler = origin;
- mLoadListener = listener;
- }
-
- /**
- * Saves this handler's state into a map.
- * @return True iff succeeds.
- */
- /* package */ synchronized boolean saveState(Bundle outState) {
- boolean success = (outState != null);
- if (success) {
- // TODO?
- outState.putBundle("ssl-error-handler", mSslPrefTable);
- }
-
- return success;
- }
-
- /**
- * Restores this handler's state from a map.
- * @return True iff succeeds.
- */
- /* package */ synchronized boolean restoreState(Bundle inState) {
- boolean success = (inState != null);
- if (success) {
- success = inState.containsKey("ssl-error-handler");
- if (success) {
- mSslPrefTable = inState.getBundle("ssl-error-handler");
- }
- }
-
- return success;
- }
-
- /**
- * Clears SSL error preference table.
- */
- /* package */ synchronized void clear() {
- mSslPrefTable.clear();
- }
-
- /**
- * Handles requests from the network stack about whether to proceed with a
- * load given an SSL error(s). We may ask the client what to do, or use a
- * cached response.
- */
- /* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
- if (DebugFlags.SSL_ERROR_HANDLER) {
- Log.v(LOGTAG, "SslErrorHandler.handleSslErrorRequest(): " +
- "url=" + loader.url());
- }
-
- if (!loader.cancelled()) {
- mLoaderQueue.offer(loader);
- if (loader == mLoaderQueue.peek()) {
- fastProcessQueuedSslErrors();
- }
- }
- }
-
- /**
- * Check the preference table to see if we already have a 'proceed' decision
- * from the client for this host and for an error of equal or greater
- * severity than the supplied error. If so, instruct the loader to proceed
- * and return true. Otherwise return false.
- */
- /* package */ synchronized boolean checkSslPrefTable(LoadListener loader,
- SslError error) {
- final String host = loader.host();
- final int primary = error.getPrimaryError();
-
- if (DebugFlags.SSL_ERROR_HANDLER) {
- assert host != null;
- assert primary != -1;
- }
-
- if (mSslPrefTable.containsKey(host) && primary <= mSslPrefTable.getInt(host)) {
- if (!loader.cancelled()) {
- loader.handleSslErrorResponse(true);
- }
- return true;
- }
- return false;
- }
-
- /**
- * Processes queued SSL-error confirmation requests in
- * a tight loop while there is no need to ask the client.
- */
- /* package */void fastProcessQueuedSslErrors() {
- while (processNextLoader());
- }
-
- /**
- * Processes the next loader in the queue.
- * @return True iff should proceed to processing the
- * following loader in the queue
- */
- private synchronized boolean processNextLoader() {
- LoadListener loader = mLoaderQueue.peek();
- if (loader != null) {
- // if this loader has been cancelled
- if (loader.cancelled()) {
- // go to the following loader in the queue. Make sure this
- // loader has been removed from the queue.
- mLoaderQueue.remove(loader);
- return true;
- }
-
- SslError error = loader.sslError();
-
- if (DebugFlags.SSL_ERROR_HANDLER) {
- assert error != null;
- }
-
- // checkSslPrefTable() will instruct the loader to proceed if we
- // have a cached 'proceed' decision. It does not remove the loader
- // from the queue.
- if (checkSslPrefTable(loader, error)) {
- mLoaderQueue.remove(loader);
- return true;
- }
-
- // If we can not proceed based on a cached decision, ask the client.
- CallbackProxy proxy = loader.getFrame().getCallbackProxy();
- proxy.onReceivedSslError(new SslErrorHandlerImpl(this, loader), error);
- }
-
- // the queue must be empty, stop
- return false;
- }
-
- /**
- * Proceed with this load.
- */
- public void proceed() {
- mOriginHandler.sendMessage(mOriginHandler.obtainMessage(
- HANDLE_RESPONSE, 1, 0, mLoadListener));
- }
-
- /**
- * Cancel this load and all pending loads for the WebView that had the
- * error.
- */
- public void cancel() {
- mOriginHandler.sendMessage(mOriginHandler.obtainMessage(
- HANDLE_RESPONSE, 0, 0, mLoadListener));
- }
-
- /**
- * Handles the response from the client about whether to proceed with this
- * load. We save the response to be re-used in the future.
- */
- /* package */ synchronized void handleSslErrorResponse(LoadListener loader,
- SslError error, boolean proceed) {
- if (DebugFlags.SSL_ERROR_HANDLER) {
- assert loader != null;
- assert error != null;
- }
-
- if (DebugFlags.SSL_ERROR_HANDLER) {
- Log.v(LOGTAG, "SslErrorHandler.handleSslErrorResponse():"
- + " proceed: " + proceed
- + " url:" + loader.url());
- }
-
- if (!loader.cancelled()) {
- if (proceed) {
- // Update the SSL error preference table
- int primary = error.getPrimaryError();
- String host = loader.host();
-
- if (DebugFlags.SSL_ERROR_HANDLER) {
- assert host != null;
- assert primary != -1;
- }
- boolean hasKey = mSslPrefTable.containsKey(host);
- if (!hasKey || primary > mSslPrefTable.getInt(host)) {
- mSslPrefTable.putInt(host, primary);
- }
- }
- loader.handleSslErrorResponse(proceed);
- }
- }
-}
diff --git a/core/java/android/webkit/StreamLoader.java b/core/java/android/webkit/StreamLoader.java
deleted file mode 100644
index 7bcd50d..0000000
--- a/core/java/android/webkit/StreamLoader.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.os.Handler;
-import android.os.Message;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * This abstract class is used for all content loaders that rely on streaming
- * content into the rendering engine loading framework.
- *
- * The class implements a state machine to load the content into the frame in
- * a similar manor to the way content arrives from the network. The class uses
- * messages to move from one state to the next, which enables async. loading of
- * the streamed content.
- *
- * Classes that inherit from this class must implement two methods, the first
- * method is used to setup the InputStream and notify the loading framework if
- * it can load it's content. The other method allows the derived class to add
- * additional HTTP headers to the response.
- *
- * By default, content loaded with a StreamLoader is marked with a HTTP header
- * that indicates the content should not be cached.
- *
- */
-abstract class StreamLoader implements Handler.Callback {
-
- private static final int MSG_STATUS = 100; // Send status to loader
- private static final int MSG_HEADERS = 101; // Send headers to loader
- private static final int MSG_DATA = 102; // Send data to loader
- private static final int MSG_END = 103; // Send endData to loader
-
- protected final Context mContext;
- protected final LoadListener mLoadListener; // loader class
- protected InputStream mDataStream; // stream to read data from
- protected long mContentLength; // content length of data
- private byte [] mData; // buffer to pass data to loader with.
-
- // Handler which will be initialized in the thread where load() is called.
- private Handler mHandler;
-
- /**
- * Constructor. Although this class calls the LoadListener, it only calls
- * the EventHandler Interface methods. LoadListener concrete class is used
- * to avoid the penality of calling an interface.
- *
- * @param loadlistener The LoadListener to call with the data.
- */
- StreamLoader(LoadListener loadlistener) {
- mLoadListener = loadlistener;
- mContext = loadlistener.getContext();
- }
-
- /**
- * This method is called when the derived class should setup mDataStream,
- * and call mLoadListener.status() to indicate that the load can occur. If it
- * fails to setup, it should still call status() with the error code.
- *
- * @return true if stream was successfully setup
- */
- protected abstract boolean setupStreamAndSendStatus();
-
- /**
- * This method is called when the headers are about to be sent to the
- * load framework. The derived class has the opportunity to add addition
- * headers.
- *
- * @param headers Map of HTTP headers that will be sent to the loader.
- */
- abstract protected void buildHeaders(Headers headers);
-
- /**
- * Calling this method starts the load of the content for this StreamLoader.
- * This method simply creates a Handler in the current thread and posts a
- * message to send the status and returns immediately.
- */
- final void load() {
- synchronized (this) {
- if (mHandler == null) {
- mHandler = new Handler(this);
- }
- }
-
- if (!mLoadListener.isSynchronous()) {
- mHandler.sendEmptyMessage(MSG_STATUS);
- } else {
- // Load the stream synchronously.
- if (setupStreamAndSendStatus()) {
- // We were able to open the stream, create the array
- // to pass data to the loader
- mData = new byte[8192];
- sendHeaders();
- while (!sendData() && !mLoadListener.cancelled());
- closeStreamAndSendEndData();
- mLoadListener.loadSynchronousMessages();
- }
- }
- }
-
- public boolean handleMessage(Message msg) {
- if (mLoadListener.isSynchronous()) {
- throw new AssertionError();
- }
- if (mLoadListener.cancelled()) {
- closeStreamAndSendEndData();
- return true;
- }
- switch(msg.what) {
- case MSG_STATUS:
- if (setupStreamAndSendStatus()) {
- // We were able to open the stream, create the array
- // to pass data to the loader
- mData = new byte[8192];
- mHandler.sendEmptyMessage(MSG_HEADERS);
- }
- break;
- case MSG_HEADERS:
- sendHeaders();
- mHandler.sendEmptyMessage(MSG_DATA);
- break;
- case MSG_DATA:
- if (sendData()) {
- mHandler.sendEmptyMessage(MSG_END);
- } else {
- mHandler.sendEmptyMessage(MSG_DATA);
- }
- break;
- case MSG_END:
- closeStreamAndSendEndData();
- break;
- default:
- return false;
- }
- return true;
- }
-
- /**
- * Construct the headers and pass them to the EventHandler.
- */
- private void sendHeaders() {
- Headers headers = new Headers();
- if (mContentLength > 0) {
- headers.setContentLength(mContentLength);
- }
- buildHeaders(headers);
- mLoadListener.headers(headers);
- }
-
- /**
- * Read data from the stream and pass it to the EventHandler.
- * If an error occurs reading the stream, then an error is sent to the
- * EventHandler, and moves onto the next state - end of data.
- * @return True if all the data has been read. False if sendData should be
- * called again.
- */
- private boolean sendData() {
- if (mDataStream != null) {
- try {
- int amount = mDataStream.read(mData);
- if (amount > 0) {
- mLoadListener.data(mData, amount);
- return false;
- }
- } catch (IOException ex) {
- mLoadListener.error(EventHandler.FILE_ERROR, ex.getMessage());
- }
- }
- return true;
- }
-
- /**
- * Close the stream and inform the EventHandler that load is complete.
- */
- private void closeStreamAndSendEndData() {
- if (mDataStream != null) {
- try {
- mDataStream.close();
- } catch (IOException ex) {
- // ignore.
- }
- }
- mLoadListener.endData();
- }
-}
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index 24e0d11..650310e 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -26,24 +26,6 @@
* response when the WebView requests a particular resource.
*/
public class WebResourceResponse {
-
- private class Loader extends StreamLoader {
- Loader(LoadListener loadListener) {
- super(loadListener);
- mDataStream = mInputStream;
- }
- @Override
- protected boolean setupStreamAndSendStatus() {
- mLoadListener.status(1, 1, mDataStream != null ? 200 : 404, "");
- return true;
- }
- @Override
- protected void buildHeaders(Headers headers) {
- headers.setContentType(mMimeType);
- headers.setContentEncoding(mEncoding);
- }
- }
-
// Accessed by jni, do not rename without modifying the jni code.
private String mMimeType;
private String mEncoding;
@@ -114,8 +96,4 @@
public InputStream getData() {
return mInputStream;
}
-
- StreamLoader loader(LoadListener listener) {
- return new Loader(listener);
- }
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 79bd35b..3da72c3 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1955,7 +1955,6 @@
public static void enablePlatformNotifications() {
checkThread();
synchronized (WebView.class) {
- Network.enablePlatformNotifications();
sNotificationsEnabled = true;
Context context = JniUtil.getContext();
if (context != null)
@@ -1973,7 +1972,6 @@
public static void disablePlatformNotifications() {
checkThread();
synchronized (WebView.class) {
- Network.disablePlatformNotifications();
sNotificationsEnabled = false;
Context context = JniUtil.getContext();
if (context != null)
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index ee27dd4..ede133c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1383,21 +1383,12 @@
Process.setThreadPriority(mTid,
Process.THREAD_PRIORITY_BACKGROUND);
pauseTimers();
- if (!JniUtil.useChromiumHttpStack()) {
- WebViewWorker.getHandler().sendEmptyMessage(
- WebViewWorker.MSG_PAUSE_CACHE_TRANSACTION);
- } else {
- nativeCloseIdleConnections(mNativeClass);
- }
+ nativeCloseIdleConnections(mNativeClass);
break;
case RESUME_TIMERS:
Process.setThreadPriority(mTid, mSavedPriority);
resumeTimers();
- if (!JniUtil.useChromiumHttpStack()) {
- WebViewWorker.getHandler().sendEmptyMessage(
- WebViewWorker.MSG_RESUME_CACHE_TRANSACTION);
- }
break;
case ON_PAUSE:
@@ -1471,14 +1462,10 @@
}
case CLEAR_SSL_PREF_TABLE:
- if (JniUtil.useChromiumHttpStack()) {
- // FIXME: This will not work for connections currently in use, as
- // they cache the certificate responses. See http://b/5324235.
- SslCertLookupTable.getInstance().clear();
- nativeCloseIdleConnections(mNativeClass);
- } else {
- Network.getInstance(mContext).clearUserSslPrefTable();
- }
+ // FIXME: This will not work for connections currently in use, as
+ // they cache the certificate responses. See http://b/5324235.
+ SslCertLookupTable.getInstance().clear();
+ nativeCloseIdleConnections(mNativeClass);
break;
case TOUCH_UP:
@@ -2426,14 +2413,6 @@
// called by JNI
private void sendNotifyProgressFinished() {
sendUpdateTextEntry();
- if (!JniUtil.useChromiumHttpStack()) {
- // as CacheManager can behave based on database transaction, we need to
- // call tick() to trigger endTransaction
- WebViewWorker.getHandler().removeMessages(
- WebViewWorker.MSG_CACHE_TRANSACTION_TICKER);
- WebViewWorker.getHandler().sendEmptyMessage(
- WebViewWorker.MSG_CACHE_TRANSACTION_TICKER);
- }
contentDraw();
}
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 695c154..757a619 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -31,9 +31,6 @@
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;
-import android.webkit.CookieManager.Cookie;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.JniUtil;
public class WebViewDatabase {
private static final String DATABASE_FILE = "webview.db";
@@ -55,39 +52,25 @@
// 10 -> 11 Drop cookies and cache now managed by the chromium stack,
// and update the form data table to use the new format
// implemented for b/5265606.
- private static final int CACHE_DATABASE_VERSION = 4;
- // 1 -> 2 Add expires String
- // 2 -> 3 Add content-disposition
- // 3 -> 4 Add crossdomain (For x-permitted-cross-domain-policies header)
private static WebViewDatabase mInstance = null;
private static SQLiteDatabase mDatabase = null;
- private static SQLiteDatabase mCacheDatabase = null;
// synchronize locks
- private final Object mCookieLock = new Object();
private final Object mPasswordLock = new Object();
private final Object mFormLock = new Object();
private final Object mHttpAuthLock = new Object();
- // TODO: The Chromium HTTP stack handles cookies independently.
- // We should consider removing the cookies table if and when we switch to
- // the Chromium HTTP stack for good.
private static final String mTableNames[] = {
- "cookies", "password", "formurl", "formdata", "httpauth"
+ "password", "formurl", "formdata", "httpauth"
};
// Table ids (they are index to mTableNames)
- private static final int TABLE_COOKIES_ID = 0;
-
- private static final int TABLE_PASSWORD_ID = 1;
-
- private static final int TABLE_FORMURL_ID = 2;
-
- private static final int TABLE_FORMDATA_ID = 3;
-
- private static final int TABLE_HTTPAUTH_ID = 4;
+ private static final int TABLE_PASSWORD_ID = 0;
+ private static final int TABLE_FORMURL_ID = 1;
+ private static final int TABLE_FORMDATA_ID = 2;
+ private static final int TABLE_HTTPAUTH_ID = 3;
// column id strings for "_id" which can be used by any table
private static final String ID_COL = "_id";
@@ -96,51 +79,9 @@
"_id"
};
- // column id strings for "cookies" table
- private static final String COOKIES_NAME_COL = "name";
-
- private static final String COOKIES_VALUE_COL = "value";
-
- private static final String COOKIES_DOMAIN_COL = "domain";
-
- private static final String COOKIES_PATH_COL = "path";
-
- private static final String COOKIES_EXPIRES_COL = "expires";
-
- private static final String COOKIES_SECURE_COL = "secure";
-
- // column id strings for "cache" table
- private static final String CACHE_URL_COL = "url";
-
- private static final String CACHE_FILE_PATH_COL = "filepath";
-
- private static final String CACHE_LAST_MODIFY_COL = "lastmodify";
-
- private static final String CACHE_ETAG_COL = "etag";
-
- private static final String CACHE_EXPIRES_COL = "expires";
-
- private static final String CACHE_EXPIRES_STRING_COL = "expiresstring";
-
- private static final String CACHE_MIMETYPE_COL = "mimetype";
-
- private static final String CACHE_ENCODING_COL = "encoding";
-
- private static final String CACHE_HTTP_STATUS_COL = "httpstatus";
-
- private static final String CACHE_LOCATION_COL = "location";
-
- private static final String CACHE_CONTENTLENGTH_COL = "contentlength";
-
- private static final String CACHE_CONTENTDISPOSITION_COL = "contentdisposition";
-
- private static final String CACHE_CROSSDOMAIN_COL = "crossdomain";
-
// column id strings for "password" table
private static final String PASSWORD_HOST_COL = "host";
-
private static final String PASSWORD_USERNAME_COL = "username";
-
private static final String PASSWORD_PASSWORD_COL = "password";
// column id strings for "formurl" table
@@ -148,38 +89,15 @@
// column id strings for "formdata" table
private static final String FORMDATA_URLID_COL = "urlid";
-
private static final String FORMDATA_NAME_COL = "name";
-
private static final String FORMDATA_VALUE_COL = "value";
// column id strings for "httpauth" table
private static final String HTTPAUTH_HOST_COL = "host";
-
private static final String HTTPAUTH_REALM_COL = "realm";
-
private static final String HTTPAUTH_USERNAME_COL = "username";
-
private static final String HTTPAUTH_PASSWORD_COL = "password";
- // use InsertHelper to improve insert performance by 40%
- private static DatabaseUtils.InsertHelper mCacheInserter;
- private static int mCacheUrlColIndex;
- private static int mCacheFilePathColIndex;
- private static int mCacheLastModifyColIndex;
- private static int mCacheETagColIndex;
- private static int mCacheExpiresColIndex;
- private static int mCacheExpiresStringColIndex;
- private static int mCacheMimeTypeColIndex;
- private static int mCacheEncodingColIndex;
- private static int mCacheHttpStatusColIndex;
- private static int mCacheLocationColIndex;
- private static int mCacheContentLengthColIndex;
- private static int mCacheContentDispositionColIndex;
- private static int mCacheCrossDomainColIndex;
-
- private static int mCacheTransactionRefcount;
-
// Initially true until the background thread completes.
private boolean mInitialized = false;
@@ -207,11 +125,9 @@
}
initDatabase(context);
- if (JniUtil.useChromiumHttpStack()) {
- context.deleteDatabase(CACHE_DATABASE_FILE);
- } else {
- initCacheDatabase(context);
- }
+ // Before using the Chromium HTTP stack, we stored the WebKit cache in
+ // our own DB. Clean up the DB file if it's still around.
+ context.deleteDatabase(CACHE_DATABASE_FILE);
// Thread done, notify.
mInitialized = true;
@@ -254,83 +170,6 @@
mDatabase.setLockingEnabled(false);
}
- private void initCacheDatabase(Context context) {
- assert !JniUtil.useChromiumHttpStack();
-
- try {
- mCacheDatabase = context.openOrCreateDatabase(
- CACHE_DATABASE_FILE, 0, null);
- } catch (SQLiteException e) {
- // try again by deleting the old db and create a new one
- if (context.deleteDatabase(CACHE_DATABASE_FILE)) {
- mCacheDatabase = context.openOrCreateDatabase(
- CACHE_DATABASE_FILE, 0, null);
- }
- }
- mCacheDatabase.enableWriteAheadLogging();
-
- // mCacheDatabase should not be null,
- // the only case is RequestAPI test has problem to create db
- if (mCacheDatabase == null) {
- mInitialized = true;
- notify();
- return;
- }
-
- if (mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
- mCacheDatabase.beginTransactionNonExclusive();
- try {
- upgradeCacheDatabase();
- bootstrapCacheDatabase();
- mCacheDatabase.setTransactionSuccessful();
- } finally {
- mCacheDatabase.endTransaction();
- }
- // Erase the files from the file system in the
- // case that the database was updated and the
- // there were existing cache content
- CacheManager.removeAllCacheFiles();
- }
-
- // use read_uncommitted to speed up READ
- mCacheDatabase.execSQL("PRAGMA read_uncommitted = true;");
- // as only READ can be called in the
- // non-WebViewWorkerThread, and read_uncommitted is used,
- // we can turn off database lock to use transaction.
- mCacheDatabase.setLockingEnabled(false);
-
- // use InsertHelper for faster insertion
- mCacheInserter =
- new DatabaseUtils.InsertHelper(mCacheDatabase,
- "cache");
- mCacheUrlColIndex = mCacheInserter
- .getColumnIndex(CACHE_URL_COL);
- mCacheFilePathColIndex = mCacheInserter
- .getColumnIndex(CACHE_FILE_PATH_COL);
- mCacheLastModifyColIndex = mCacheInserter
- .getColumnIndex(CACHE_LAST_MODIFY_COL);
- mCacheETagColIndex = mCacheInserter
- .getColumnIndex(CACHE_ETAG_COL);
- mCacheExpiresColIndex = mCacheInserter
- .getColumnIndex(CACHE_EXPIRES_COL);
- mCacheExpiresStringColIndex = mCacheInserter
- .getColumnIndex(CACHE_EXPIRES_STRING_COL);
- mCacheMimeTypeColIndex = mCacheInserter
- .getColumnIndex(CACHE_MIMETYPE_COL);
- mCacheEncodingColIndex = mCacheInserter
- .getColumnIndex(CACHE_ENCODING_COL);
- mCacheHttpStatusColIndex = mCacheInserter
- .getColumnIndex(CACHE_HTTP_STATUS_COL);
- mCacheLocationColIndex = mCacheInserter
- .getColumnIndex(CACHE_LOCATION_COL);
- mCacheContentLengthColIndex = mCacheInserter
- .getColumnIndex(CACHE_CONTENTLENGTH_COL);
- mCacheContentDispositionColIndex = mCacheInserter
- .getColumnIndex(CACHE_CONTENTDISPOSITION_COL);
- mCacheCrossDomainColIndex = mCacheInserter
- .getColumnIndex(CACHE_CROSSDOMAIN_COL);
- }
-
private static void upgradeDatabase() {
upgradeDatabaseToV10();
upgradeDatabaseFromV10ToV11();
@@ -347,14 +186,12 @@
return;
}
- if (JniUtil.useChromiumHttpStack()) {
- // Clear out old java stack cookies - this data is now stored in
- // a separate database managed by the Chrome stack.
- mDatabase.execSQL("DROP TABLE IF EXISTS " + mTableNames[TABLE_COOKIES_ID]);
+ // Clear out old java stack cookies - this data is now stored in
+ // a separate database managed by the Chrome stack.
+ mDatabase.execSQL("DROP TABLE IF EXISTS cookies");
- // Likewise for the old cache table.
- mDatabase.execSQL("DROP TABLE IF EXISTS cache");
- }
+ // Likewise for the old cache table.
+ mDatabase.execSQL("DROP TABLE IF EXISTS cache");
// Update form autocomplete URLs to match new ICS formatting.
Cursor c = mDatabase.query(mTableNames[TABLE_FORMURL_ID], null, null,
@@ -397,8 +234,7 @@
return;
}
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_COOKIES_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS cookies");
mDatabase.execSQL("DROP TABLE IF EXISTS cache");
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_FORMURL_ID]);
@@ -409,16 +245,6 @@
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_PASSWORD_ID]);
- // cookies
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
- + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
- + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
- + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
- mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
- + mTableNames[TABLE_COOKIES_ID] + " (path)");
-
// formurl
mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
+ " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
@@ -449,36 +275,6 @@
+ ") ON CONFLICT REPLACE);");
}
- private static void upgradeCacheDatabase() {
- int oldVersion = mCacheDatabase.getVersion();
- if (oldVersion != 0) {
- Log.i(LOGTAG, "Upgrading cache database from version "
- + oldVersion + " to "
- + CACHE_DATABASE_VERSION + ", which will destroy all old data");
- }
- mCacheDatabase.execSQL("DROP TABLE IF EXISTS cache");
- mCacheDatabase.setVersion(CACHE_DATABASE_VERSION);
- }
-
- private static void bootstrapCacheDatabase() {
- if (mCacheDatabase != null) {
- mCacheDatabase.execSQL("CREATE TABLE cache"
- + " (" + ID_COL + " INTEGER PRIMARY KEY, " + CACHE_URL_COL
- + " TEXT, " + CACHE_FILE_PATH_COL + " TEXT, "
- + CACHE_LAST_MODIFY_COL + " TEXT, " + CACHE_ETAG_COL
- + " TEXT, " + CACHE_EXPIRES_COL + " INTEGER, "
- + CACHE_EXPIRES_STRING_COL + " TEXT, "
- + CACHE_MIMETYPE_COL + " TEXT, " + CACHE_ENCODING_COL
- + " TEXT," + CACHE_HTTP_STATUS_COL + " INTEGER, "
- + CACHE_LOCATION_COL + " TEXT, " + CACHE_CONTENTLENGTH_COL
- + " INTEGER, " + CACHE_CONTENTDISPOSITION_COL + " TEXT, "
- + CACHE_CROSSDOMAIN_COL + " TEXT,"
- + " UNIQUE (" + CACHE_URL_COL + ") ON CONFLICT REPLACE);");
- mCacheDatabase.execSQL("CREATE INDEX cacheUrlIndex ON cache ("
- + CACHE_URL_COL + ")");
- }
- }
-
// Wait for the background initialization thread to complete and check the
// database creation status.
private boolean checkInitialized() {
@@ -516,422 +312,6 @@
}
//
- // cookies functions
- //
-
- /**
- * Get cookies in the format of CookieManager.Cookie inside an ArrayList for
- * a given domain
- *
- * @return ArrayList<Cookie> If nothing is found, return an empty list.
- */
- ArrayList<Cookie> getCookiesForDomain(String domain) {
- ArrayList<Cookie> list = new ArrayList<Cookie>();
- if (domain == null || !checkInitialized()) {
- return list;
- }
-
- synchronized (mCookieLock) {
- final String[] columns = new String[] {
- ID_COL, COOKIES_DOMAIN_COL, COOKIES_PATH_COL,
- COOKIES_NAME_COL, COOKIES_VALUE_COL, COOKIES_EXPIRES_COL,
- COOKIES_SECURE_COL
- };
- final String selection = "(" + COOKIES_DOMAIN_COL
- + " GLOB '*' || ?)";
- Cursor cursor = null;
- try {
- cursor = mDatabase.query(mTableNames[TABLE_COOKIES_ID],
- columns, selection, new String[] { domain }, null, null,
- null);
- if (cursor.moveToFirst()) {
- int domainCol = cursor.getColumnIndex(COOKIES_DOMAIN_COL);
- int pathCol = cursor.getColumnIndex(COOKIES_PATH_COL);
- int nameCol = cursor.getColumnIndex(COOKIES_NAME_COL);
- int valueCol = cursor.getColumnIndex(COOKIES_VALUE_COL);
- int expiresCol = cursor.getColumnIndex(COOKIES_EXPIRES_COL);
- int secureCol = cursor.getColumnIndex(COOKIES_SECURE_COL);
- do {
- Cookie cookie = new Cookie();
- cookie.domain = cursor.getString(domainCol);
- cookie.path = cursor.getString(pathCol);
- cookie.name = cursor.getString(nameCol);
- cookie.value = cursor.getString(valueCol);
- if (cursor.isNull(expiresCol)) {
- cookie.expires = -1;
- } else {
- cookie.expires = cursor.getLong(expiresCol);
- }
- cookie.secure = cursor.getShort(secureCol) != 0;
- cookie.mode = Cookie.MODE_NORMAL;
- list.add(cookie);
- } while (cursor.moveToNext());
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getCookiesForDomain", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return list;
- }
- }
-
- /**
- * Delete cookies which matches (domain, path, name).
- *
- * @param domain If it is null, nothing happens.
- * @param path If it is null, all the cookies match (domain) will be
- * deleted.
- * @param name If it is null, all the cookies match (domain, path) will be
- * deleted.
- */
- void deleteCookies(String domain, String path, String name) {
- if (domain == null || !checkInitialized()) {
- return;
- }
-
- synchronized (mCookieLock) {
- final String where = "(" + COOKIES_DOMAIN_COL + " == ?) AND ("
- + COOKIES_PATH_COL + " == ?) AND (" + COOKIES_NAME_COL
- + " == ?)";
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], where,
- new String[] { domain, path, name });
- }
- }
-
- /**
- * Add a cookie to the database
- *
- * @param cookie
- */
- void addCookie(Cookie cookie) {
- if (cookie.domain == null || cookie.path == null || cookie.name == null
- || !checkInitialized()) {
- return;
- }
-
- synchronized (mCookieLock) {
- ContentValues cookieVal = new ContentValues();
- cookieVal.put(COOKIES_DOMAIN_COL, cookie.domain);
- cookieVal.put(COOKIES_PATH_COL, cookie.path);
- cookieVal.put(COOKIES_NAME_COL, cookie.name);
- cookieVal.put(COOKIES_VALUE_COL, cookie.value);
- if (cookie.expires != -1) {
- cookieVal.put(COOKIES_EXPIRES_COL, cookie.expires);
- }
- cookieVal.put(COOKIES_SECURE_COL, cookie.secure);
- mDatabase.insert(mTableNames[TABLE_COOKIES_ID], null, cookieVal);
- }
- }
-
- /**
- * Whether there is any cookies in the database
- *
- * @return TRUE if there is cookie.
- */
- boolean hasCookies() {
- synchronized (mCookieLock) {
- return hasEntries(TABLE_COOKIES_ID);
- }
- }
-
- /**
- * Clear cookie database
- */
- void clearCookies() {
- if (!checkInitialized()) {
- return;
- }
-
- synchronized (mCookieLock) {
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], null, null);
- }
- }
-
- /**
- * Clear session cookies, which means cookie doesn't have EXPIRES.
- */
- void clearSessionCookies() {
- if (!checkInitialized()) {
- return;
- }
-
- final String sessionExpired = COOKIES_EXPIRES_COL + " ISNULL";
- synchronized (mCookieLock) {
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], sessionExpired,
- null);
- }
- }
-
- /**
- * Clear expired cookies
- *
- * @param now Time for now
- */
- void clearExpiredCookies(long now) {
- if (!checkInitialized()) {
- return;
- }
-
- final String expires = COOKIES_EXPIRES_COL + " <= ?";
- synchronized (mCookieLock) {
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], expires,
- new String[] { Long.toString(now) });
- }
- }
-
- //
- // cache functions
- //
-
- // only called from WebViewWorkerThread
- boolean startCacheTransaction() {
- if (++mCacheTransactionRefcount == 1) {
- if (!Thread.currentThread().equals(
- WebViewWorker.getHandler().getLooper().getThread())) {
- Log.w(LOGTAG, "startCacheTransaction should be called from "
- + "WebViewWorkerThread instead of from "
- + Thread.currentThread().getName());
- }
- mCacheDatabase.beginTransactionNonExclusive();
- return true;
- }
- return false;
- }
-
- // only called from WebViewWorkerThread
- boolean endCacheTransaction() {
- if (--mCacheTransactionRefcount == 0) {
- if (!Thread.currentThread().equals(
- WebViewWorker.getHandler().getLooper().getThread())) {
- Log.w(LOGTAG, "endCacheTransaction should be called from "
- + "WebViewWorkerThread instead of from "
- + Thread.currentThread().getName());
- }
- try {
- mCacheDatabase.setTransactionSuccessful();
- } finally {
- mCacheDatabase.endTransaction();
- }
- return true;
- }
- return false;
- }
-
- /**
- * Get a cache item.
- *
- * @param url The url
- * @return CacheResult The CacheManager.CacheResult
- */
- CacheResult getCache(String url) {
- assert !JniUtil.useChromiumHttpStack();
-
- if (url == null || !checkInitialized()) {
- return null;
- }
-
- Cursor cursor = null;
- final String query = "SELECT filepath, lastmodify, etag, expires, "
- + "expiresstring, mimetype, encoding, httpstatus, location, contentlength, "
- + "contentdisposition, crossdomain FROM cache WHERE url = ?";
- try {
- cursor = mCacheDatabase.rawQuery(query, new String[] { url });
- if (cursor.moveToFirst()) {
- CacheResult ret = new CacheResult();
- ret.localPath = cursor.getString(0);
- ret.lastModified = cursor.getString(1);
- ret.etag = cursor.getString(2);
- ret.expires = cursor.getLong(3);
- ret.expiresString = cursor.getString(4);
- ret.mimeType = cursor.getString(5);
- ret.encoding = cursor.getString(6);
- ret.httpStatusCode = cursor.getInt(7);
- ret.location = cursor.getString(8);
- ret.contentLength = cursor.getLong(9);
- ret.contentdisposition = cursor.getString(10);
- ret.crossDomain = cursor.getString(11);
- return ret;
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getCache", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return null;
- }
-
- /**
- * Remove a cache item.
- *
- * @param url The url
- */
- void removeCache(String url) {
- assert !JniUtil.useChromiumHttpStack();
-
- if (url == null || !checkInitialized()) {
- return;
- }
-
- mCacheDatabase.execSQL("DELETE FROM cache WHERE url = ?", new String[] { url });
- }
-
- /**
- * Add or update a cache. CACHE_URL_COL is unique in the table.
- *
- * @param url The url
- * @param c The CacheManager.CacheResult
- */
- void addCache(String url, CacheResult c) {
- assert !JniUtil.useChromiumHttpStack();
-
- if (url == null || !checkInitialized()) {
- return;
- }
-
- mCacheInserter.prepareForInsert();
- mCacheInserter.bind(mCacheUrlColIndex, url);
- mCacheInserter.bind(mCacheFilePathColIndex, c.localPath);
- mCacheInserter.bind(mCacheLastModifyColIndex, c.lastModified);
- mCacheInserter.bind(mCacheETagColIndex, c.etag);
- mCacheInserter.bind(mCacheExpiresColIndex, c.expires);
- mCacheInserter.bind(mCacheExpiresStringColIndex, c.expiresString);
- mCacheInserter.bind(mCacheMimeTypeColIndex, c.mimeType);
- mCacheInserter.bind(mCacheEncodingColIndex, c.encoding);
- mCacheInserter.bind(mCacheHttpStatusColIndex, c.httpStatusCode);
- mCacheInserter.bind(mCacheLocationColIndex, c.location);
- mCacheInserter.bind(mCacheContentLengthColIndex, c.contentLength);
- mCacheInserter.bind(mCacheContentDispositionColIndex,
- c.contentdisposition);
- mCacheInserter.bind(mCacheCrossDomainColIndex, c.crossDomain);
- mCacheInserter.execute();
- }
-
- /**
- * Clear cache database
- */
- void clearCache() {
- if (!checkInitialized()) {
- return;
- }
-
- mCacheDatabase.delete("cache", null, null);
- }
-
- boolean hasCache() {
- if (!checkInitialized()) {
- return false;
- }
-
- Cursor cursor = null;
- boolean ret = false;
- try {
- cursor = mCacheDatabase.query("cache", ID_PROJECTION,
- null, null, null, null, null);
- ret = cursor.moveToFirst() == true;
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "hasCache", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return ret;
- }
-
- long getCacheTotalSize() {
- if (mCacheDatabase == null) {
- return 0;
- }
- long size = 0;
- Cursor cursor = null;
- final String query = "SELECT SUM(contentlength) as sum FROM cache";
- try {
- cursor = mCacheDatabase.rawQuery(query, null);
- if (cursor.moveToFirst()) {
- size = cursor.getLong(0);
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getCacheTotalSize", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return size;
- }
-
- List<String> trimCache(long amount) {
- ArrayList<String> pathList = new ArrayList<String>(100);
- Cursor cursor = null;
- final String query = "SELECT contentlength, filepath FROM cache ORDER BY expires ASC";
- try {
- cursor = mCacheDatabase.rawQuery(query, null);
- if (cursor.moveToFirst()) {
- int batchSize = 100;
- StringBuilder pathStr = new StringBuilder(20 + 16 * batchSize);
- pathStr.append("DELETE FROM cache WHERE filepath IN (?");
- for (int i = 1; i < batchSize; i++) {
- pathStr.append(", ?");
- }
- pathStr.append(")");
- SQLiteStatement statement = null;
- try {
- statement = mCacheDatabase.compileStatement(
- pathStr.toString());
- // as bindString() uses 1-based index, initialize index to 1
- int index = 1;
- do {
- long length = cursor.getLong(0);
- if (length == 0) {
- continue;
- }
- amount -= length;
- String filePath = cursor.getString(1);
- statement.bindString(index, filePath);
- pathList.add(filePath);
- if (index++ == batchSize) {
- statement.execute();
- statement.clearBindings();
- index = 1;
- }
- } while (cursor.moveToNext() && amount > 0);
- if (index > 1) {
- // there may be old bindings from the previous statement
- // if index is less than batchSize, which is Ok.
- statement.execute();
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "trimCache SQLiteStatement", e);
- } finally {
- if (statement != null) statement.close();
- }
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "trimCache Cursor", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return pathList;
- }
-
- List<String> getAllCacheFileNames() {
- ArrayList<String> pathList = null;
- Cursor cursor = null;
- try {
- cursor = mCacheDatabase.rawQuery("SELECT filepath FROM cache",
- null);
- if (cursor != null && cursor.moveToFirst()) {
- pathList = new ArrayList<String>(cursor.getCount());
- do {
- pathList.add(cursor.getString(0));
- } while (cursor.moveToNext());
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getAllCacheFileNames", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return pathList;
- }
-
- //
// password functions
//
diff --git a/core/java/android/webkit/WebViewWorker.java b/core/java/android/webkit/WebViewWorker.java
deleted file mode 100644
index 6a4ca29..0000000
--- a/core/java/android/webkit/WebViewWorker.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import android.net.http.Headers;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-
-/**
- * WebViewWorker executes in a separate thread other than UI and WebViewCore. To
- * avoid blocking UI or WebKit's execution, the caller can send a message to
- * WebViewWorker.getHandler() and it will be handled in the WebViewWorkerThread.
- */
-final class WebViewWorker extends Handler {
-
- private static final String THREAD_NAME = "WebViewWorkerThread";
-
- private static WebViewWorker sWorkerHandler;
-
- private static Map<LoadListener, CacheManager.CacheResult> mCacheResultMap
- = new HashMap<LoadListener, CacheManager.CacheResult>();
-
- /**
- * Package level class to be used while creating a cache entry.
- */
- static class CacheCreateData {
- LoadListener mListener;
- String mUrl;
- String mMimeType;
- int mStatusCode;
- long mPostId;
- Headers mHeaders;
- }
-
- /**
- * Package level class to be used while saving a cache entry.
- */
- static class CacheSaveData {
- LoadListener mListener;
- String mUrl;
- long mPostId;
- }
-
- /**
- * Package level class to be used while updating a cache entry's encoding.
- */
- static class CacheEncoding {
- LoadListener mListener;
- String mEncoding;
- }
-
- /**
- * Package level class to be used while appending data to a cache entry.
- */
- static class CacheData {
- LoadListener mListener;
- ByteArrayBuilder.Chunk mChunk;
- }
-
- static synchronized WebViewWorker getHandler() {
- if (sWorkerHandler == null) {
- HandlerThread thread = new HandlerThread(THREAD_NAME,
- android.os.Process.THREAD_PRIORITY_DEFAULT
- + android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
- thread.start();
- sWorkerHandler = new WebViewWorker(thread.getLooper());
- }
- return sWorkerHandler;
- }
-
- private WebViewWorker(Looper looper) {
- super(looper);
- }
-
- // trigger transaction once a minute
- private static final int CACHE_TRANSACTION_TICKER_INTERVAL = 60 * 1000;
-
- private static boolean mCacheTickersBlocked = true;
-
- // message ids
- static final int MSG_ADD_STREAMLOADER = 101;
- static final int MSG_ADD_HTTPLOADER = 102;
- static final int MSG_CREATE_CACHE = 103;
- static final int MSG_UPDATE_CACHE_ENCODING = 104;
- static final int MSG_APPEND_CACHE = 105;
- static final int MSG_SAVE_CACHE = 106;
- static final int MSG_REMOVE_CACHE = 107;
- static final int MSG_TRIM_CACHE = 108;
- static final int MSG_CLEAR_CACHE = 109;
- static final int MSG_CACHE_TRANSACTION_TICKER = 110;
- static final int MSG_PAUSE_CACHE_TRANSACTION = 111;
- static final int MSG_RESUME_CACHE_TRANSACTION = 112;
-
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case MSG_ADD_STREAMLOADER: {
- StreamLoader loader = (StreamLoader) msg.obj;
- loader.load();
- break;
- }
- case MSG_ADD_HTTPLOADER: {
- FrameLoader loader = (FrameLoader) msg.obj;
- loader.handleHTTPLoad();
- break;
- }
- case MSG_CREATE_CACHE: {
- assert !JniUtil.useChromiumHttpStack();
- CacheCreateData data = (CacheCreateData) msg.obj;
- CacheManager.CacheResult cache = CacheManager.createCacheFile(
- data.mUrl, data.mStatusCode, data.mHeaders,
- data.mMimeType, data.mPostId, false);
- if (cache != null) {
- mCacheResultMap.put(data.mListener, cache);
- } else {
- mCacheResultMap.remove(data.mListener);
- }
- break;
- }
- case MSG_UPDATE_CACHE_ENCODING: {
- assert !JniUtil.useChromiumHttpStack();
- CacheEncoding data = (CacheEncoding) msg.obj;
- CacheManager.CacheResult cache = mCacheResultMap
- .get(data.mListener);
- if (cache != null) {
- cache.encoding = data.mEncoding;
- }
- break;
- }
- case MSG_APPEND_CACHE: {
- assert !JniUtil.useChromiumHttpStack();
- CacheData data = (CacheData) msg.obj;
- CacheManager.CacheResult cache = mCacheResultMap
- .get(data.mListener);
- if (cache != null) {
- cache.contentLength += data.mChunk.mLength;
- if (cache.contentLength > CacheManager.CACHE_MAX_SIZE) {
- CacheManager.cleanupCacheFile(cache);
- mCacheResultMap.remove(data.mListener);
- } else {
- try {
- cache.outStream.write(data.mChunk.mArray, 0,
- data.mChunk.mLength);
- } catch (IOException e) {
- CacheManager.cleanupCacheFile(cache);
- mCacheResultMap.remove(data.mListener);
- }
- }
- }
- data.mChunk.release();
- break;
- }
- case MSG_SAVE_CACHE: {
- assert !JniUtil.useChromiumHttpStack();
- CacheSaveData data = (CacheSaveData) msg.obj;
- CacheManager.CacheResult cache = mCacheResultMap
- .get(data.mListener);
- if (cache != null) {
- CacheManager.saveCacheFile(data.mUrl, data.mPostId, cache);
- mCacheResultMap.remove(data.mListener);
- }
- break;
- }
- case MSG_REMOVE_CACHE: {
- assert !JniUtil.useChromiumHttpStack();
- LoadListener listener = (LoadListener) msg.obj;
- CacheManager.CacheResult cache = mCacheResultMap.get(listener);
- if (cache != null) {
- CacheManager.cleanupCacheFile(cache);
- mCacheResultMap.remove(listener);
- }
- break;
- }
- case MSG_TRIM_CACHE: {
- assert !JniUtil.useChromiumHttpStack();
- CacheManager.trimCacheIfNeeded();
- break;
- }
- case MSG_CLEAR_CACHE: {
- assert !JniUtil.useChromiumHttpStack();
- CacheManager.clearCache();
- break;
- }
- case MSG_CACHE_TRANSACTION_TICKER: {
- assert !JniUtil.useChromiumHttpStack();
- if (!mCacheTickersBlocked) {
- CacheManager.endTransaction();
- CacheManager.startTransaction();
- sendEmptyMessageDelayed(MSG_CACHE_TRANSACTION_TICKER,
- CACHE_TRANSACTION_TICKER_INTERVAL);
- }
- break;
- }
- case MSG_PAUSE_CACHE_TRANSACTION: {
- assert !JniUtil.useChromiumHttpStack();
- if (CacheManager.disableTransaction()) {
- mCacheTickersBlocked = true;
- removeMessages(MSG_CACHE_TRANSACTION_TICKER);
- }
- break;
- }
- case MSG_RESUME_CACHE_TRANSACTION: {
- assert !JniUtil.useChromiumHttpStack();
- if (CacheManager.enableTransaction()) {
- mCacheTickersBlocked = false;
- sendEmptyMessageDelayed(MSG_CACHE_TRANSACTION_TICKER,
- CACHE_TRANSACTION_TICKER_INTERVAL);
- }
- break;
- }
- }
- }
-}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 3f9ba47..1524cbe 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -61,20 +61,26 @@
$(TOP)/external/openssl/include \
LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libmedia \
- libutils \
- libcutils \
- libui \
- libsonivox \
- libvorbisidec \
+ libbinder \
+ libmedia \
+ libutils \
+ libcutils \
+ libui \
+ libsonivox \
+ libvorbisidec \
libstagefright_yuv \
libcamera_client \
- libdrmframework \
- libcrypto \
- libssl \
- libgui \
+ libdrmframework \
+ libcrypto \
+ libssl \
+ libgui \
libstagefright_omx \
+ liblog \
+ libicuuc \
+ libicui18n \
+ libz \
+ libdl \
+ libchromium_net \
LOCAL_STATIC_LIBRARIES := \
libstagefright_color_conversion \
@@ -88,51 +94,14 @@
libstagefright_httplive \
libstagefright_id3 \
libFLAC \
+ libstagefright_chromium_http \
-################################################################################
-
-# The following was shamelessly copied from external/webkit/Android.mk and
-# currently must follow the same logic to determine how webkit was built and
-# if it's safe to link against libchromium_net
-
-# See if the user has specified a stack they want to use
-HTTP_STACK = $(HTTP)
-# We default to the Chrome HTTP stack.
-DEFAULT_HTTP = chrome
-ALT_HTTP = android
-
-ifneq ($(HTTP_STACK),chrome)
- ifneq ($(HTTP_STACK),android)
- # No HTTP stack is specified, pickup the one we want as default.
- ifeq ($(USE_ALT_HTTP),true)
- HTTP_STACK = $(ALT_HTTP)
- else
- HTTP_STACK = $(DEFAULT_HTTP)
- endif
- endif
-endif
-
-ifeq ($(HTTP_STACK),chrome)
-
-LOCAL_SHARED_LIBRARIES += \
- liblog \
- libicuuc \
- libicui18n \
- libz \
- libdl \
-
-LOCAL_STATIC_LIBRARIES += \
- libstagefright_chromium_http
-
-LOCAL_SHARED_LIBRARIES += libstlport libchromium_net
+LOCAL_SHARED_LIBRARIES += libstlport
include external/stlport/libstlport.mk
+# TODO: Chromium is always available, so this flag can be removed.
LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
-endif # ifeq ($(HTTP_STACK),chrome)
-
-################################################################################
-
LOCAL_SHARED_LIBRARIES += \
libstagefright_enc_common \
libstagefright_avc_common \