CookieManager.java revision 851730552166bf6e99ed60438ba91f09f36b829f
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.webkit; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ParseException; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.WebAddress; 217cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilsonimport android.net.http.AndroidHttpClient; 22851730552166bf6e99ed60438ba91f09f36b829fKristian Monsenimport android.os.AsyncTask; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2545a9a14006214e6478311ffcb980e766702d5a76Doug Zongker 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collection; 29f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Klobaimport java.util.Comparator; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.LinkedHashMap; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 33f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Klobaimport java.util.SortedSet; 34f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Klobaimport java.util.TreeSet; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CookieManager manages cookies according to RFC2109 spec. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class CookieManager { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static CookieManager sRef; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String LOGTAG = "webkit"; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String DOMAIN = "domain"; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String PATH = "path"; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String EXPIRES = "expires"; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String SECURE = "secure"; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String MAX_AGE = "max-age"; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String HTTP_ONLY = "httponly"; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String HTTPS = "https"; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char PERIOD = '.'; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char COMMA = ','; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char SEMICOLON = ';'; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char EQUAL = '='; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char PATH_DELIM = '/'; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char QUESTION_MARK = '?'; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char WHITE_SPACE = ' '; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char QUOTATION = '\"'; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SECURE_LENGTH = SECURE.length(); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int HTTP_ONLY_LENGTH = HTTP_ONLY.length(); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RFC2109 defines 4k as maximum size of a cookie 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_COOKIE_LENGTH = 4 * 1024; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RFC2109 defines 20 as max cookie count per domain. As we track with base 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // domain, we allow 50 per base domain 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_COOKIE_COUNT_PER_BASE_DOMAIN = 50; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RFC2109 defines 300 as max count of domains. As we track with base 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // domain, we set 200 as max base domain count 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_DOMAIN_COUNT = 200; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // max cookie count to limit RAM cookie takes less than 100k, it is based on 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // average cookie entry size is less than 100 bytes 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_RAM_COOKIES_COUNT = 1000; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // max domain count to limit RAM cookie takes less than 100k, 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_RAM_DOMAIN_COUNT = 15; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Map<String, ArrayList<Cookie>> mCookieMap = new LinkedHashMap 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project <String, ArrayList<Cookie>>(MAX_DOMAIN_COUNT, 0.75f, true); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAcceptCookie = true; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1022d80ede01afde8a0f484f012e395a97e04e32d36Steve Block // TODO: Remove this if/when we permanently switch to the Chromium HTTP stack 1032d80ede01afde8a0f484f012e395a97e04e32d36Steve Block // http:/b/3118772 1042d80ede01afde8a0f484f012e395a97e04e32d36Steve Block private static Boolean sUseChromiumHttpStack; 1052d80ede01afde8a0f484f012e395a97e04e32d36Steve Block 106851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen private int pendingCookieOperations = 0; 107851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This contains a list of 2nd-level domains that aren't allowed to have 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wildcards when combined with country-codes. For example: [.co.uk]. 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String[] BAD_COUNTRY_2LDS = 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info", 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "lg", "ne", "net", "or", "org" }; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Arrays.sort(BAD_COUNTRY_2LDS); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level class to be accessed by cookie sync manager 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class Cookie { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_NEW = 0; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_NORMAL = 1; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_DELETED = 2; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_REPLACED = 3; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String domain; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String path; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long expires; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lastAcessTime; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lastUpdateTime; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean secure; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte mode; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie() { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie(String defaultDomain, String defaultPath) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project domain = defaultDomain; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project path = defaultPath; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expires = -1; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean exactMatch(Cookie in) { 1606a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // An exact match means that domain, path, and name are equal. If 1616a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // both values are null, the cookies match. If both values are 1626a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // non-null, the cookies match. If one value is null and the other 1636a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // is non-null, the cookies do not match (i.e. "foo=;" and "foo;") 1646a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott boolean valuesMatch = !((value == null) ^ (in.value == null)); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return domain.equals(in.domain) && path.equals(in.path) && 1666a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott name.equals(in.name) && valuesMatch; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean domainMatch(String urlHost) { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (domain.startsWith(".")) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlHost.endsWith(domain.substring(1))) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = domain.length(); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int urlLen = urlHost.length(); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlLen > len - 1) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure bar.com doesn't match .ar.com 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlHost.charAt(urlLen - len) == PERIOD; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // exact match if domain is not leading w/ dot 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlHost.equals(domain); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean pathMatch(String urlPath) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlPath.startsWith(path)) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = path.length(); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(LOGTAG, "Empty cookie path"); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int urlLen = urlPath.length(); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path.charAt(len-1) != PATH_DELIM && urlLen > len) { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure /wee doesn't match /we 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlPath.charAt(len) == PATH_DELIM; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "domain: " + domain + "; path: " + path + "; name: " + name 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "; value: " + value; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 210f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba private static final CookieComparator COMPARATOR = new CookieComparator(); 211f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 212f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba private static final class CookieComparator implements Comparator<Cookie> { 213f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba public int compare(Cookie cookie1, Cookie cookie2) { 2148ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // According to RFC 2109, multiple cookies are ordered in a way such 2158ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // that those with more specific Path attributes precede those with 2168ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // less specific. Ordering with respect to other attributes (e.g., 2178ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // Domain) is unspecified. 2188ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // As Set is not modified if the two objects are same, we do want to 2198ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // assign different value for each cookie. 2208ae277735439940480e1301ff729cee32c2ab72eGrace Kloba int diff = cookie2.path.length() - cookie1.path.length(); 2216a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (diff != 0) return diff; 2226a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 2236a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott diff = cookie2.domain.length() - cookie1.domain.length(); 2246a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (diff != 0) return diff; 2256a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 2266a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // If cookie2 has a null value, it should come later in 2276a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // the list. 2286a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (cookie2.value == null) { 2292807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott // If both cookies have null values, fall back to using the name 2302807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott // difference. 2312807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott if (cookie1.value != null) { 2322807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott return -1; 2332807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott } 2346a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } else if (cookie1.value == null) { 2356a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Now we know that cookie2 does not have a null value, if 2366a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // cookie1 has a null value, place it later in the list. 2376a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott return 1; 2388ae277735439940480e1301ff729cee32c2ab72eGrace Kloba } 2396a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 24006312cae6b0e00c4ccbe84e9c682de8d607897a9Patrick Scott // Fallback to comparing the name to ensure consistent order. 24106312cae6b0e00c4ccbe84e9c682de8d607897a9Patrick Scott return cookie1.name.compareTo(cookie2.name); 242f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 243f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 244f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CookieManager() { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Object clone() throws CloneNotSupportedException { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new CloneNotSupportedException("doesn't implement Cloneable"); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a singleton CookieManager. If this is called before any 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link WebView} is created or outside of {@link WebView} context, the 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller needs to call {@link CookieSyncManager#createInstance(Context)} 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * first. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return CookieManager 25906312cae6b0e00c4ccbe84e9c682de8d607897a9Patrick Scott */ 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static synchronized CookieManager getInstance() { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sRef == null) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRef = new CookieManager(); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sRef; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2672d80ede01afde8a0f484f012e395a97e04e32d36Steve Block private static boolean useChromiumHttpStack() { 2682d80ede01afde8a0f484f012e395a97e04e32d36Steve Block if (sUseChromiumHttpStack == null) { 2692d80ede01afde8a0f484f012e395a97e04e32d36Steve Block sUseChromiumHttpStack = nativeUseChromiumHttpStack(); 2702d80ede01afde8a0f484f012e395a97e04e32d36Steve Block } 2712d80ede01afde8a0f484f012e395a97e04e32d36Steve Block return sUseChromiumHttpStack; 2722d80ede01afde8a0f484f012e395a97e04e32d36Steve Block } 2732d80ede01afde8a0f484f012e395a97e04e32d36Steve Block 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Control whether cookie is enabled or disabled 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param accept TRUE if accept cookie 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setAcceptCookie(boolean accept) { 279b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block if (useChromiumHttpStack()) { 280b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block nativeSetAcceptCookie(accept); 281b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block return; 282b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block } 283b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAcceptCookie = accept; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return whether cookie is enabled 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return TRUE if accept cookie 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean acceptCookie() { 292b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block if (useChromiumHttpStack()) { 293b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block return nativeAcceptCookie(); 294b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block } 295b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAcceptCookie; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set cookie for a given url. The old cookie with same host/path/name will 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be removed. The new cookie will be added if it is not expired or it does 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have expiration which implies it is session cookie. 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url The url which cookie is set for 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value for set-cookie: in http response header 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCookie(String url, String value) { 30793e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block if (useChromiumHttpStack()) { 30893e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block nativeSetCookie(url, value); 30993e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block return; 31093e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block } 31193e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WebAddress uri; 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = new WebAddress(url); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ParseException ex) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "Bad address: " + url); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCookie(uri, value); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set cookie for a given uri. The old cookie with same host/path/name will 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be removed. The new cookie will be added if it is not expired or it does 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have expiration which implies it is session cookie. 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The uri which cookie is set for 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value for set-cookie: in http response header 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide - hide this because it takes in a parameter of type WebAddress, 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a system private class. 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setCookie(WebAddress uri, String value) { 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value != null && value.length() > MAX_COOKIE_LENGTH) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAcceptCookie || uri == null) { 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3382e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] hostAndPath = getHostAndPath(uri); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath == null) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For default path, when setting a cookie, the spec says: 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //Path: Defaults to the path of the request URL that generated the 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set-Cookie response, up to, but not including, the 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // right-most /. 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath[1].length() > 1) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = hostAndPath[1].lastIndexOf(PATH_DELIM); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hostAndPath[1] = hostAndPath[1].substring(0, 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index > 0 ? index : index + 1); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookies = null; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookies = parseCookie(hostAndPath[0], hostAndPath[1], value); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException ex) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "parse cookie failed for: " + value); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookies == null || cookies.size() == 0) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(hostAndPath[0]); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList == null) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList = CookieSyncManager.getInstance() 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getCookiesForDomain(baseDomain); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.put(baseDomain, cookieList); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = cookies.size(); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = cookies.get(i); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean done = false; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = cookieList.iterator(); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookieEntry = iter.next(); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.exactMatch(cookieEntry)) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires < 0 || cookie.expires > now) { 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // secure cookies can't be overwritten by non-HTTPS url 390eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert if (!cookieEntry.secure || HTTPS.equals(uri.getScheme())) { 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.value = cookie.value; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.expires = cookie.expires; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.secure = cookie.secure; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastAcessTime = now; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastUpdateTime = now; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.mode = Cookie.MODE_REPLACED; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastUpdateTime = now; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.mode = Cookie.MODE_DELETED; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project done = true; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise negative means 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // far future 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!done && (cookie.expires < 0 || cookie.expires > now)) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastAcessTime = now; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastUpdateTime = now; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.mode = Cookie.MODE_NEW; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList.size() > MAX_COOKIE_COUNT_PER_BASE_DOMAIN) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie toDelete = new Cookie(); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete.lastAcessTime = now; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter2 = cookieList.iterator(); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter2.hasNext()) { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookieEntry2 = iter2.next(); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((cookieEntry2.lastAcessTime < toDelete.lastAcessTime) 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieEntry2.mode != Cookie.MODE_DELETED) { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete = cookieEntry2; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete.mode = Cookie.MODE_DELETED; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList.add(cookie); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get cookie(s) for a given url so that it can be set to "cookie:" in http 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request header. 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url The url needs cookie 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getCookie(String url) { 438dcd2d0dee9fb70f7e1e813355ed382a38e23fb46Steve Block if (useChromiumHttpStack()) { 439dcd2d0dee9fb70f7e1e813355ed382a38e23fb46Steve Block return nativeGetCookie(url); 440dcd2d0dee9fb70f7e1e813355ed382a38e23fb46Steve Block } 441dcd2d0dee9fb70f7e1e813355ed382a38e23fb46Steve Block 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WebAddress uri; 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = new WebAddress(url); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ParseException ex) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "Bad address: " + url); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getCookie(uri); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get cookie(s) for a given uri so that it can be set to "cookie:" in http 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request header. 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The uri needs cookie 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide - hide this because it has a parameter of type WebAddress, which 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is a system private class. 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String getCookie(WebAddress uri) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAcceptCookie || uri == null) { 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] hostAndPath = getHostAndPath(uri); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath == null) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(hostAndPath[0]); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList == null) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList = CookieSyncManager.getInstance() 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getCookiesForDomain(baseDomain); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.put(baseDomain, cookieList); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 479eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert boolean secure = HTTPS.equals(uri.getScheme()); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = cookieList.iterator(); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 482f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba SortedSet<Cookie> cookieSet = new TreeSet<Cookie>(COMPARATOR); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.domainMatch(hostAndPath[0]) && 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.pathMatch(hostAndPath[1]) 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (cookie.expires < 0 || cookie.expires > now) 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (!cookie.secure || secure) 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookie.mode != Cookie.MODE_DELETED) { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastAcessTime = now; 493f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba cookieSet.add(cookie); 494f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 495f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 497f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba StringBuilder ret = new StringBuilder(256); 498f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba Iterator<Cookie> setIter = cookieSet.iterator(); 499f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba while (setIter.hasNext()) { 500f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba Cookie cookie = setIter.next(); 501f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba if (ret.length() > 0) { 502f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(SEMICOLON); 503f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba // according to RC2109, SEMICOLON is official separator, 504f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba // but when log in yahoo.com, it needs WHITE_SPACE too. 505f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(WHITE_SPACE); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 507f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 508f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(cookie.name); 5096a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (cookie.value != null) { 5106a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott ret.append(EQUAL); 5116a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott ret.append(cookie.value); 5126a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 514f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret.length() > 0) { 5162e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5212e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "getCookie: uri: " + uri 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " But can't find cookie."); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen synchronized void waitForCookieOperationsToComplete() { 530851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen while (pendingCookieOperations > 0) { 531851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen try { 532851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen wait(); 533851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen } catch (InterruptedException e) { } 534851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen } 535851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen } 536851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen 537851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen private synchronized void signalCookieOperationsComplete() { 538851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen pendingCookieOperations--; 539851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen assert pendingCookieOperations > -1; 540851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen notify(); 541851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen } 542851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen 543851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen private synchronized void signalCookieOperationsStart() { 544851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen pendingCookieOperations++; 545851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen } 546851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all session cookies, which are cookies without expiration date 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeSessionCookie() { 551851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen signalCookieOperationsStart(); 55293e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block if (useChromiumHttpStack()) { 553851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen new AsyncTask<Void, Void, Void>() { 554851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen protected Void doInBackground(Void... none) { 555851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen nativeRemoveSessionCookie(); 556851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen signalCookieOperationsComplete(); 557851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen return null; 558851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen } 559851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen }.execute(); 56093e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block return; 56193e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block } 56293e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires == -1) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iter.remove(); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearSessionCookies(); 579851730552166bf6e99ed60438ba91f09f36b829fKristian Monsen signalCookieOperationsComplete(); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all cookies 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeAllCookie() { 5902d80ede01afde8a0f484f012e395a97e04e32d36Steve Block if (useChromiumHttpStack()) { 5912d80ede01afde8a0f484f012e395a97e04e32d36Steve Block nativeRemoveAllCookie(); 5922d80ede01afde8a0f484f012e395a97e04e32d36Steve Block return; 5932d80ede01afde8a0f484f012e395a97e04e32d36Steve Block } 5942d80ede01afde8a0f484f012e395a97e04e32d36Steve Block 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap = new LinkedHashMap<String, ArrayList<Cookie>>( 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MAX_DOMAIN_COUNT, 0.75f, true); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearAllCookies(); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return true if there are stored cookies. 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean hasCookies() { 61193e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block if (useChromiumHttpStack()) { 61293e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block return nativeHasCookies(); 61393e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block } 61493e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return CookieSyncManager.getInstance().hasCookies(); 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all expired cookies 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeExpiredCookie() { 62293e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block if (useChromiumHttpStack()) { 62393e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block nativeRemoveExpiredCookie(); 62493e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block return; 62593e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block } 62693e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires > 0 && cookie.expires < now) { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iter.remove(); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearExpiredCookies(now); 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 65399f39771ab15fc13d221ebfb3682741002c5f7b1Iain Merrick * Package level api, called from CookieSyncManager 654c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick * 65599f39771ab15fc13d221ebfb3682741002c5f7b1Iain Merrick * Flush all cookies managed by the Chrome HTTP stack to flash. 656c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick */ 65799f39771ab15fc13d221ebfb3682741002c5f7b1Iain Merrick void flushCookieStore() { 658c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick if (useChromiumHttpStack()) { 659c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick nativeFlushCookieStore(); 660c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick } 661c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick } 662c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick 663c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick /** 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a list of cookies which are updated since a given time. 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param last The given time in millisec 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of cookies 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized ArrayList<Cookie> getUpdatedCookiesSince(long last) { 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookies = new ArrayList<Cookie>(); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.lastUpdateTime > last) { 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookies.add(cookie); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cookies; 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete a Cookie in the RAM 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookie Cookie to be deleted 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void deleteACookie(Cookie cookie) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.mode == Cookie.MODE_DELETED) { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(cookie.domain); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList != null) { 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList.remove(cookie); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList.isEmpty()) { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.remove(baseDomain); 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called after a cookie is synced to FLASH 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookie Cookie to be synced 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void syncedACookie(Cookie cookie) { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.mode = Cookie.MODE_NORMAL; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete the least recent used domains if the total cookie count in RAM 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exceeds the limit 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of cookies which are removed from RAM 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized ArrayList<Cookie> deleteLRUDomain() { 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int byteCount = 0; 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mapSize = mCookieMap.size(); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapSize < MAX_RAM_DOMAIN_COUNT) { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieLists = mCookieMap.values(); 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator(); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 7332e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 14 is 3 * sizeof(long) + sizeof(boolean) 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // + sizeof(byte) 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteCount += cookie.domain.length() 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.path.length() 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.name.length() 7426a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott + (cookie.value != null 7436a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott ? cookie.value.length() 7446a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott : 0) 7456a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott + 14; 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += list.size(); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> retlist = new ArrayList<Cookie>(); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) { 7562e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, count + " cookies used " + byteCount 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " bytes with " + mapSize + " domains"); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] domains = mCookieMap.keySet().toArray(); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int toGo = mapSize / 10 + 1; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (toGo-- > 0){ 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String domain = domains[toGo].toString(); 7642e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "delete domain: " + domain 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " from RAM cache"); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retlist.addAll(mCookieMap.get(domain)); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.remove(domain); 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retlist; 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extract the host and path out of a uri 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The given WebAddress 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The host and path in the format of String[], String[0] is host 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which has at least two periods, String[1] is path which always 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ended with "/" 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] getHostAndPath(WebAddress uri) { 783eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert if (uri.getHost() != null && uri.getPath() != null) { 78411fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger 78511fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger /* 78611fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger * The domain (i.e. host) portion of the cookie is supposed to be 78711fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger * case-insensitive. We will consistently return the domain in lower 78811fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger * case, which allows us to do the more efficient equals comparison 78911fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger * instead of equalIgnoreCase. 79011fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger * 79111fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger * See: http://www.ieft.org/rfc/rfc2965.txt (Section 3.3.3) 79211fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger */ 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] ret = new String[2]; 794eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert ret[0] = uri.getHost().toLowerCase(); 795eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert ret[1] = uri.getPath(); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = ret[0].indexOf(PERIOD); 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == -1) { 799eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert if (uri.getScheme().equalsIgnoreCase("file")) { 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // There is a potential bug where a local file path matches 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // another file in the local web server directory. Still 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "localhost" is the best pseudo domain name. 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = "localhost"; 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (index == ret[0].lastIndexOf(PERIOD)) { 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cookie host must have at least two periods 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = PERIOD + ret[0]; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret[1].charAt(0) != PATH_DELIM) { 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * find cookie path, e.g. for http://www.google.com, the path is "/" 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab/, the path is "/lab" 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab/foo, the path is "/lab/foo" 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab?hl=en, the path is "/lab" 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab.asp?hl=en, the path is "/lab.asp" 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: the path from URI has at least one "/" 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See: 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.unix.com.ua/rfc/rfc2109.html 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = ret[1].indexOf(QUESTION_MARK); 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index != -1) { 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[1] = ret[1].substring(0, index); 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 82811fb6144604fbd1148695421e9ab6896701a431bDerek Sollenberger 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the base domain for a give host. E.g. mail.google.com will return 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * google.com 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param host The give host 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the base domain 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getBaseDomain(String host) { 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startIndex = 0; 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextIndex = host.indexOf(PERIOD); 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastIndex = host.lastIndexOf(PERIOD); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextIndex < lastIndex) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startIndex = nextIndex + 1; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextIndex = host.indexOf(PERIOD, startIndex); 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startIndex > 0) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return host.substring(startIndex); 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return host; 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parseCookie() parses the cookieString which is a comma-separated list of 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one or more cookies in the format of "NAME=VALUE; expires=DATE; 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * path=PATH; domain=DOMAIN_NAME; secure httponly" to a list of Cookies. 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Here is a sample: IGDND=1, IGPC=ET=UB8TSNwtDmQ:AF=0; expires=Sun, 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 17-Jan-2038 19:14:07 GMT; path=/ig; domain=.google.com, =, 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PREF=ID=408909b1b304593d:TM=1156459854:LM=1156459854:S=V-vCAU6Sh-gobCfO; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com which 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * contains 3 cookies IGDND, IGPC, PREF and an empty cookie 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param host The default host 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The default path 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookieString The string coming from "Set-Cookie:" 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of Cookies 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<Cookie> parseCookie(String host, String path, 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String cookieString) { 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> ret = new ArrayList<Cookie>(); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = cookieString.length(); 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = null; 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // done 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= length) { 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip white space 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == WHITE_SPACE) { 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * get NAME=VALUE; pair. detecting the end of a pair is tricky, it 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can be the end of a string, like "foo=bluh", it can be semicolon 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * like "foo=bluh;path=/"; or it can be enclosed by \", like 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "foo=\"bluh bluh\";path=/" 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it as one cookie instead of two cookies. 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 898ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int semicolonIndex = cookieString.indexOf(SEMICOLON, index); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int equalIndex = cookieString.indexOf(EQUAL, index); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie = new Cookie(host, path); 9016a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 9026a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Cookies like "testcookie; path=/;" are valid and used 903d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // (lovefilm.se). 904d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // Look for 2 cases: 905d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // 1. "foo" or "foo;" where equalIndex is -1 906d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // 2. "foo; path=..." where the first semicolon is before an equal 907d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // and a semicolon exists. 908d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott if ((semicolonIndex != -1 && (semicolonIndex < equalIndex)) || 909d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott equalIndex == -1) { 9106a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Fix up the index in case we have a string like "testcookie" 9116a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (semicolonIndex == -1) { 9126a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex = length; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9146a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.name = cookieString.substring(index, semicolonIndex); 9156a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = null; 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9176a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.name = cookieString.substring(index, equalIndex); 918d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // Make sure we do not throw an exception if the cookie is like 919d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // "foo=" 920d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott if ((equalIndex < length - 1) && 921d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott (cookieString.charAt(equalIndex + 1) == QUOTATION)) { 9226a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott index = cookieString.indexOf(QUOTATION, equalIndex + 2); 9236a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (index == -1) { 9246a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // bad format, force return 9256a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott break; 9266a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 9276a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 9286a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Get the semicolon index again in case it was contained within 9296a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // the quotations. 9306a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex = cookieString.indexOf(SEMICOLON, index); 9316a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (semicolonIndex == -1) { 9326a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex = length; 9336a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 9346a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (semicolonIndex - equalIndex > MAX_COOKIE_LENGTH) { 9356a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // cookie is too big, trim it 9366a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = cookieString.substring(equalIndex + 1, 9376a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott equalIndex + 1 + MAX_COOKIE_LENGTH); 9386a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } else if (equalIndex + 1 == semicolonIndex 9396a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott || semicolonIndex < equalIndex) { 940d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // this is an unusual case like "foo=;" or "foo=" 9416a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = ""; 9426a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } else { 9436a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = cookieString.substring(equalIndex + 1, 9446a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex); 9456a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get attributes 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = semicolonIndex; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // done 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= length) { 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip white space and semicolon 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == WHITE_SPACE 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || cookieString.charAt(index) == SEMICOLON) { 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // comma means next cookie 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == COMMA) { 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "secure" is a known attribute doesn't use "="; 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while sites like live.com uses "secure=" 970dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (length - index >= SECURE_LENGTH 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieString.substring(index, index + SECURE_LENGTH). 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalsIgnoreCase(SECURE)) { 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index += SECURE_LENGTH; 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.secure = true; 975dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (index == length) break; 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == EQUAL) index++; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "httponly" is a known attribute doesn't use "="; 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while sites like live.com uses "httponly=" 982dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (length - index >= HTTP_ONLY_LENGTH 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieString.substring(index, 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index + HTTP_ONLY_LENGTH). 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalsIgnoreCase(HTTP_ONLY)) { 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index += HTTP_ONLY_LENGTH; 987dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (index == length) break; 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == EQUAL) index++; 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME: currently only parse the attribute 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalIndex = cookieString.indexOf(EQUAL, index); 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (equalIndex > 0) { 99487ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom String name = cookieString.substring(index, equalIndex).toLowerCase(); 99587ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom int valueIndex = equalIndex + 1; 99687ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom while (valueIndex < length && cookieString.charAt(valueIndex) == WHITE_SPACE) { 99787ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom valueIndex++; 99887ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom } 99987ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals(EXPIRES)) { 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int comaIndex = cookieString.indexOf(COMMA, equalIndex); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip ',' in (Wdy, DD-Mon-YYYY HH:MM:SS GMT) or 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (Weekday, DD-Mon-YY HH:MM:SS GMT) if it applies. 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "Wednesday" is the longest Weekday which has length 9 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((comaIndex != -1) && 100787ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom (comaIndex - valueIndex <= 10)) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = comaIndex + 1; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project semicolonIndex = cookieString.indexOf(SEMICOLON, index); 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int commaIndex = cookieString.indexOf(COMMA, index); 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (semicolonIndex == -1 && commaIndex == -1) { 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = length; 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (semicolonIndex == -1) { 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = commaIndex; 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (commaIndex == -1) { 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = semicolonIndex; 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = Math.min(semicolonIndex, commaIndex); 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 102287ad930037a5ccb915d3ff3675135d405af092d7Brian Carlstrom String value = cookieString.substring(valueIndex, index); 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strip quotes if they exist 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 2 && value.charAt(0) == QUOTATION) { 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int endQuote = value.indexOf(QUOTATION, 1); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endQuote > 0) { 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.substring(1, endQuote); 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals(EXPIRES)) { 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10337cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson cookie.expires = AndroidHttpClient.parseDate(value); 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalArgumentException ex) { 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "illegal format for expires: " + value); 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(MAX_AGE)) { 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.expires = System.currentTimeMillis() + 1000 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Long.parseLong(value); 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "illegal format for max-age: " + value); 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(PATH)) { 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only allow non-empty path value 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 0) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.path = value; 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(DOMAIN)) { 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastPeriod = value.lastIndexOf(PERIOD); 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPeriod == 0) { 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // disallow cookies set for TLDs like [.com] 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer.parseInt(value.substring(lastPeriod + 1)); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no wildcard for ip address match 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!value.equals(host)) { 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no cross-site cookie 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore the exception, value is a host name 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.toLowerCase(); 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.charAt(0) != PERIOD) { 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pre-pended dot to make it as a domain cookie 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = PERIOD + value; 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastPeriod++; 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (host.endsWith(value.substring(1))) { 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = value.length(); 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hostLen = host.length(); 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostLen > (len - 1) 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && host.charAt(hostLen - len) != PERIOD) { 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure the bar.com doesn't match .ar.com 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // disallow cookies set on ccTLDs like [.co.uk] 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((len == lastPeriod + 3) 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (len >= 6 && len <= 8)) { 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = value.substring(1, lastPeriod); 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Arrays.binarySearch(BAD_COUNTRY_2LDS, s) >= 0) { 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = value; 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no cross-site or more specific sub-domain cookie 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bad format, force return 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = length; 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie != null && cookie.domain != null) { 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.add(cookie); 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11101c9ca4f1fa8ce06217c8c53da7f539d23ee11a1fSteve Block 11111c9ca4f1fa8ce06217c8c53da7f539d23ee11a1fSteve Block // Native functions 11122d80ede01afde8a0f484f012e395a97e04e32d36Steve Block private static native boolean nativeUseChromiumHttpStack(); 1113b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block private static native boolean nativeAcceptCookie(); 1114dcd2d0dee9fb70f7e1e813355ed382a38e23fb46Steve Block private static native String nativeGetCookie(String url); 111593e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block private static native boolean nativeHasCookies(); 11161c9ca4f1fa8ce06217c8c53da7f539d23ee11a1fSteve Block private static native void nativeRemoveAllCookie(); 111793e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block private static native void nativeRemoveExpiredCookie(); 111893e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block private static native void nativeRemoveSessionCookie(); 1119b5ac9de4b587aa8bf4de704fe9a783d9b4bea514Steve Block private static native void nativeSetAcceptCookie(boolean accept); 112093e5e14240ffbb42dbda30dc143d8dd8a132dcf9Steve Block private static native void nativeSetCookie(String url, String value); 1121c40fc2c31a55f7e8312aa2721bf51fcb74bb3a95Iain Merrick private static native void nativeFlushCookieStore(); 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1123