Merge "Drop support for Android HTTP stack"
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 d13210aa..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 e21e9ef8..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 4d7ade51..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 de78210..5601dca 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2048,7 +2048,6 @@
public static void enablePlatformNotifications() {
checkThread();
synchronized (WebView.class) {
- Network.enablePlatformNotifications();
sNotificationsEnabled = true;
Context context = JniUtil.getContext();
if (context != null)
@@ -2066,7 +2065,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 e7d3238..037e323 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1402,21 +1402,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:
@@ -1490,14 +1481,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:
@@ -2445,14 +2432,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 829f657..cfb1e29 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -63,20 +63,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 \
@@ -90,51 +96,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 \