CookieManager.java revision 45a9a14006214e6478311ffcb980e766702d5a76
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; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2345a9a14006214e6478311ffcb980e766702d5a76Doug Zongkerimport com.android.common.HttpDateTime; 2445a9a14006214e6478311ffcb980e766702d5a76Doug Zongker 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collection; 28f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Klobaimport java.util.Comparator; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.LinkedHashMap; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 32f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Klobaimport java.util.SortedSet; 33f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Klobaimport java.util.TreeSet; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CookieManager manages cookies according to RFC2109 spec. 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class CookieManager { 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static CookieManager sRef; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String LOGTAG = "webkit"; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String DOMAIN = "domain"; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String PATH = "path"; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String EXPIRES = "expires"; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String SECURE = "secure"; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String MAX_AGE = "max-age"; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String HTTP_ONLY = "httponly"; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String HTTPS = "https"; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char PERIOD = '.'; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char COMMA = ','; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char SEMICOLON = ';'; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char EQUAL = '='; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char PATH_DELIM = '/'; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char QUESTION_MARK = '?'; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char WHITE_SPACE = ' '; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final char QUOTATION = '\"'; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SECURE_LENGTH = SECURE.length(); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int HTTP_ONLY_LENGTH = HTTP_ONLY.length(); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RFC2109 defines 4k as maximum size of a cookie 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_COOKIE_LENGTH = 4 * 1024; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RFC2109 defines 20 as max cookie count per domain. As we track with base 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // domain, we allow 50 per base domain 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_COOKIE_COUNT_PER_BASE_DOMAIN = 50; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RFC2109 defines 300 as max count of domains. As we track with base 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // domain, we set 200 as max base domain count 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_DOMAIN_COUNT = 200; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // max cookie count to limit RAM cookie takes less than 100k, it is based on 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // average cookie entry size is less than 100 bytes 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_RAM_COOKIES_COUNT = 1000; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // max domain count to limit RAM cookie takes less than 100k, 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_RAM_DOMAIN_COUNT = 15; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Map<String, ArrayList<Cookie>> mCookieMap = new LinkedHashMap 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project <String, ArrayList<Cookie>>(MAX_DOMAIN_COUNT, 0.75f, true); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAcceptCookie = true; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This contains a list of 2nd-level domains that aren't allowed to have 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wildcards when combined with country-codes. For example: [.co.uk]. 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String[] BAD_COUNTRY_2LDS = 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info", 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "lg", "ne", "net", "or", "org" }; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Arrays.sort(BAD_COUNTRY_2LDS); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level class to be accessed by cookie sync manager 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class Cookie { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_NEW = 0; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_NORMAL = 1; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_DELETED = 2; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final byte MODE_REPLACED = 3; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String domain; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String path; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long expires; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lastAcessTime; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lastUpdateTime; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean secure; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte mode; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie() { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie(String defaultDomain, String defaultPath) { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project domain = defaultDomain; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project path = defaultPath; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expires = -1; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean exactMatch(Cookie in) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return domain.equals(in.domain) && path.equals(in.path) && 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name.equals(in.name); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean domainMatch(String urlHost) { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (domain.startsWith(".")) { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlHost.endsWith(domain.substring(1))) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = domain.length(); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int urlLen = urlHost.length(); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlLen > len - 1) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure bar.com doesn't match .ar.com 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlHost.charAt(urlLen - len) == PERIOD; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // exact match if domain is not leading w/ dot 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlHost.equals(domain); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean pathMatch(String urlPath) { 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlPath.startsWith(path)) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = path.length(); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(LOGTAG, "Empty cookie path"); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int urlLen = urlPath.length(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path.charAt(len-1) != PATH_DELIM && urlLen > len) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure /wee doesn't match /we 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlPath.charAt(len) == PATH_DELIM; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "domain: " + domain + "; path: " + path + "; name: " + name 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "; value: " + value; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 198f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba private static final CookieComparator COMPARATOR = new CookieComparator(); 199f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 200f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba private static final class CookieComparator implements Comparator<Cookie> { 201f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba public int compare(Cookie cookie1, Cookie cookie2) { 2028ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // According to RFC 2109, multiple cookies are ordered in a way such 2038ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // that those with more specific Path attributes precede those with 2048ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // less specific. Ordering with respect to other attributes (e.g., 2058ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // Domain) is unspecified. 2068ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // As Set is not modified if the two objects are same, we do want to 2078ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // assign different value for each cookie. 2088ae277735439940480e1301ff729cee32c2ab72eGrace Kloba int diff = cookie2.path.length() - cookie1.path.length(); 2098ae277735439940480e1301ff729cee32c2ab72eGrace Kloba if (diff == 0) { 2108ae277735439940480e1301ff729cee32c2ab72eGrace Kloba diff = cookie2.domain.length() - cookie1.domain.length(); 2118ae277735439940480e1301ff729cee32c2ab72eGrace Kloba if (diff == 0) { 2128ae277735439940480e1301ff729cee32c2ab72eGrace Kloba diff = cookie2.name.hashCode() - cookie1.name.hashCode(); 2138ae277735439940480e1301ff729cee32c2ab72eGrace Kloba if (diff == 0) { 2148ae277735439940480e1301ff729cee32c2ab72eGrace Kloba Log.w(LOGTAG, "Found two cookies with the same value." + 2158ae277735439940480e1301ff729cee32c2ab72eGrace Kloba "cookie1=" + cookie1 + " , cookie2=" + cookie2); 2168ae277735439940480e1301ff729cee32c2ab72eGrace Kloba } 2178ae277735439940480e1301ff729cee32c2ab72eGrace Kloba } 2188ae277735439940480e1301ff729cee32c2ab72eGrace Kloba } 2198ae277735439940480e1301ff729cee32c2ab72eGrace Kloba return diff; 220f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 221f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 222f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CookieManager() { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Object clone() throws CloneNotSupportedException { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new CloneNotSupportedException("doesn't implement Cloneable"); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a singleton CookieManager. If this is called before any 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link WebView} is created or outside of {@link WebView} context, the 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller needs to call {@link CookieSyncManager#createInstance(Context)} 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * first. 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return CookieManager 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project= */ 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static synchronized CookieManager getInstance() { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sRef == null) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRef = new CookieManager(); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sRef; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Control whether cookie is enabled or disabled 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param accept TRUE if accept cookie 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setAcceptCookie(boolean accept) { 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAcceptCookie = accept; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return whether cookie is enabled 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return TRUE if accept cookie 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean acceptCookie() { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAcceptCookie; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set cookie for a given url. The old cookie with same host/path/name will 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be removed. The new cookie will be added if it is not expired or it does 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have expiration which implies it is session cookie. 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url The url which cookie is set for 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value for set-cookie: in http response header 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCookie(String url, String value) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WebAddress uri; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = new WebAddress(url); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ParseException ex) { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "Bad address: " + url); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCookie(uri, value); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set cookie for a given uri. The old cookie with same host/path/name will 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be removed. The new cookie will be added if it is not expired or it does 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have expiration which implies it is session cookie. 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The uri which cookie is set for 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value for set-cookie: in http response header 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide - hide this because it takes in a parameter of type WebAddress, 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a system private class. 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setCookie(WebAddress uri, String value) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value != null && value.length() > MAX_COOKIE_LENGTH) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAcceptCookie || uri == null) { 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2952e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] hostAndPath = getHostAndPath(uri); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath == null) { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For default path, when setting a cookie, the spec says: 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //Path: Defaults to the path of the request URL that generated the 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set-Cookie response, up to, but not including, the 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // right-most /. 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath[1].length() > 1) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = hostAndPath[1].lastIndexOf(PATH_DELIM); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hostAndPath[1] = hostAndPath[1].substring(0, 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index > 0 ? index : index + 1); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookies = null; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookies = parseCookie(hostAndPath[0], hostAndPath[1], value); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException ex) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "parse cookie failed for: " + value); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookies == null || cookies.size() == 0) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(hostAndPath[0]); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList == null) { 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList = CookieSyncManager.getInstance() 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getCookiesForDomain(baseDomain); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.put(baseDomain, cookieList); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = cookies.size(); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = cookies.get(i); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean done = false; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = cookieList.iterator(); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookieEntry = iter.next(); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.exactMatch(cookieEntry)) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires < 0 || cookie.expires > now) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // secure cookies can't be overwritten by non-HTTPS url 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!cookieEntry.secure || HTTPS.equals(uri.mScheme)) { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.value = cookie.value; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.expires = cookie.expires; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.secure = cookie.secure; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastAcessTime = now; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastUpdateTime = now; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.mode = Cookie.MODE_REPLACED; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastUpdateTime = now; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.mode = Cookie.MODE_DELETED; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project done = true; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise negative means 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // far future 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!done && (cookie.expires < 0 || cookie.expires > now)) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastAcessTime = now; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastUpdateTime = now; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.mode = Cookie.MODE_NEW; 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList.size() > MAX_COOKIE_COUNT_PER_BASE_DOMAIN) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie toDelete = new Cookie(); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete.lastAcessTime = now; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter2 = cookieList.iterator(); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter2.hasNext()) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookieEntry2 = iter2.next(); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((cookieEntry2.lastAcessTime < toDelete.lastAcessTime) 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieEntry2.mode != Cookie.MODE_DELETED) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete = cookieEntry2; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete.mode = Cookie.MODE_DELETED; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList.add(cookie); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get cookie(s) for a given url so that it can be set to "cookie:" in http 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request header. 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url The url needs cookie 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getCookie(String url) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WebAddress uri; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = new WebAddress(url); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ParseException ex) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "Bad address: " + url); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getCookie(uri); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get cookie(s) for a given uri so that it can be set to "cookie:" in http 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request header. 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The uri needs cookie 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide - hide this because it has a parameter of type WebAddress, which 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is a system private class. 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String getCookie(WebAddress uri) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAcceptCookie || uri == null) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] hostAndPath = getHostAndPath(uri); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath == null) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(hostAndPath[0]); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList == null) { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList = CookieSyncManager.getInstance() 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getCookiesForDomain(baseDomain); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.put(baseDomain, cookieList); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean secure = HTTPS.equals(uri.mScheme); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = cookieList.iterator(); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 435f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba SortedSet<Cookie> cookieSet = new TreeSet<Cookie>(COMPARATOR); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.domainMatch(hostAndPath[0]) && 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.pathMatch(hostAndPath[1]) 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (cookie.expires < 0 || cookie.expires > now) 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (!cookie.secure || secure) 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookie.mode != Cookie.MODE_DELETED) { 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastAcessTime = now; 446f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba cookieSet.add(cookie); 447f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 448f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 450f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba StringBuilder ret = new StringBuilder(256); 451f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba Iterator<Cookie> setIter = cookieSet.iterator(); 452f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba while (setIter.hasNext()) { 453f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba Cookie cookie = setIter.next(); 454f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba if (ret.length() > 0) { 455f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(SEMICOLON); 456f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba // according to RC2109, SEMICOLON is official separator, 457f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba // but when log in yahoo.com, it needs WHITE_SPACE too. 458f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(WHITE_SPACE); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 460f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 461f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(cookie.name); 462f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(EQUAL); 463f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(cookie.value); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 465f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret.length() > 0) { 4672e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4722e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "getCookie: uri: " + uri 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " But can't find cookie."); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all session cookies, which are cookies without expiration date 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeSessionCookie() { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires == -1) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iter.remove(); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearSessionCookies(); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all cookies 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeAllCookie() { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap = new LinkedHashMap<String, ArrayList<Cookie>>( 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MAX_DOMAIN_COUNT, 0.75f, true); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearAllCookies(); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return true if there are stored cookies. 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean hasCookies() { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return CookieSyncManager.getInstance().hasCookies(); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all expired cookies 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeExpiredCookie() { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires > 0 && cookie.expires < now) { 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iter.remove(); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearExpiredCookies(now); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a list of cookies which are updated since a given time. 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param last The given time in millisec 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of cookies 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized ArrayList<Cookie> getUpdatedCookiesSince(long last) { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookies = new ArrayList<Cookie>(); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.lastUpdateTime > last) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookies.add(cookie); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cookies; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete a Cookie in the RAM 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookie Cookie to be deleted 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void deleteACookie(Cookie cookie) { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.mode == Cookie.MODE_DELETED) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(cookie.domain); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList != null) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList.remove(cookie); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList.isEmpty()) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.remove(baseDomain); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called after a cookie is synced to FLASH 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookie Cookie to be synced 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void syncedACookie(Cookie cookie) { 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.mode = Cookie.MODE_NORMAL; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete the least recent used domains if the total cookie count in RAM 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exceeds the limit 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of cookies which are removed from RAM 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized ArrayList<Cookie> deleteLRUDomain() { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int byteCount = 0; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mapSize = mCookieMap.size(); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapSize < MAX_RAM_DOMAIN_COUNT) { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieLists = mCookieMap.values(); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator(); 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 6282e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 14 is 3 * sizeof(long) + sizeof(boolean) 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // + sizeof(byte) 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteCount += cookie.domain.length() 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.path.length() 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.name.length() 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.value.length() + 14; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += list.size(); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> retlist = new ArrayList<Cookie>(); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) { 6482e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, count + " cookies used " + byteCount 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " bytes with " + mapSize + " domains"); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] domains = mCookieMap.keySet().toArray(); 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int toGo = mapSize / 10 + 1; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (toGo-- > 0){ 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String domain = domains[toGo].toString(); 6562e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "delete domain: " + domain 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " from RAM cache"); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retlist.addAll(mCookieMap.get(domain)); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.remove(domain); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retlist; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extract the host and path out of a uri 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The given WebAddress 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The host and path in the format of String[], String[0] is host 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which has at least two periods, String[1] is path which always 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ended with "/" 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] getHostAndPath(WebAddress uri) { 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri.mHost != null && uri.mPath != null) { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] ret = new String[2]; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = uri.mHost; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[1] = uri.mPath; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = ret[0].indexOf(PERIOD); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == -1) { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri.mScheme.equalsIgnoreCase("file")) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // There is a potential bug where a local file path matches 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // another file in the local web server directory. Still 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "localhost" is the best pseudo domain name. 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = "localhost"; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (index == ret[0].lastIndexOf(PERIOD)) { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cookie host must have at least two periods 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = PERIOD + ret[0]; 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret[1].charAt(0) != PATH_DELIM) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * find cookie path, e.g. for http://www.google.com, the path is "/" 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab/, the path is "/lab" 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab/foo, the path is "/lab/foo" 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab?hl=en, the path is "/lab" 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab.asp?hl=en, the path is "/lab.asp" 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: the path from URI has at least one "/" 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See: 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.unix.com.ua/rfc/rfc2109.html 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = ret[1].indexOf(QUESTION_MARK); 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index != -1) { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[1] = ret[1].substring(0, index); 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the base domain for a give host. E.g. mail.google.com will return 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * google.com 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param host The give host 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the base domain 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getBaseDomain(String host) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startIndex = 0; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextIndex = host.indexOf(PERIOD); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastIndex = host.lastIndexOf(PERIOD); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextIndex < lastIndex) { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startIndex = nextIndex + 1; 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextIndex = host.indexOf(PERIOD, startIndex); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startIndex > 0) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return host.substring(startIndex); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return host; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parseCookie() parses the cookieString which is a comma-separated list of 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one or more cookies in the format of "NAME=VALUE; expires=DATE; 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * path=PATH; domain=DOMAIN_NAME; secure httponly" to a list of Cookies. 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Here is a sample: IGDND=1, IGPC=ET=UB8TSNwtDmQ:AF=0; expires=Sun, 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 17-Jan-2038 19:14:07 GMT; path=/ig; domain=.google.com, =, 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PREF=ID=408909b1b304593d:TM=1156459854:LM=1156459854:S=V-vCAU6Sh-gobCfO; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com which 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * contains 3 cookies IGDND, IGPC, PREF and an empty cookie 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param host The default host 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The default path 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookieString The string coming from "Set-Cookie:" 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of Cookies 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<Cookie> parseCookie(String host, String path, 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String cookieString) { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> ret = new ArrayList<Cookie>(); 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = cookieString.length(); 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = null; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // done 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= length) { 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip white space 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == WHITE_SPACE) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * get NAME=VALUE; pair. detecting the end of a pair is tricky, it 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can be the end of a string, like "foo=bluh", it can be semicolon 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * like "foo=bluh;path=/"; or it can be enclosed by \", like 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "foo=\"bluh bluh\";path=/" 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it as one cookie instead of two cookies. 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 780ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int semicolonIndex = cookieString.indexOf(SEMICOLON, index); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int equalIndex = cookieString.indexOf(EQUAL, index); 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (equalIndex == -1) { 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bad format, force return 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 786ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (semicolonIndex > -1 && semicolonIndex < equalIndex) { 787ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // empty cookie, like "; path=/", return 788ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project break; 789ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie = new Cookie(host, path); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.name = cookieString.substring(index, equalIndex); 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(equalIndex + 1) == QUOTATION) { 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = cookieString.indexOf(QUOTATION, equalIndex + 2); 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == -1) { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bad format, force return 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project semicolonIndex = cookieString.indexOf(SEMICOLON, index); 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (semicolonIndex == -1) { 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project semicolonIndex = length; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (semicolonIndex - equalIndex > MAX_COOKIE_LENGTH) { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cookie is too big, trim it 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.value = cookieString.substring(equalIndex + 1, 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalIndex + MAX_COOKIE_LENGTH); 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (equalIndex + 1 == semicolonIndex 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || semicolonIndex < equalIndex) { 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these are unusual case like foo=; and foo; path=/ 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.value = ""; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.value = cookieString.substring(equalIndex + 1, 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project semicolonIndex); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get attributes 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = semicolonIndex; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // done 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= length) { 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip white space and semicolon 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == WHITE_SPACE 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || cookieString.charAt(index) == SEMICOLON) { 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // comma means next cookie 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == COMMA) { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "secure" is a known attribute doesn't use "="; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while sites like live.com uses "secure=" 838dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (length - index >= SECURE_LENGTH 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieString.substring(index, index + SECURE_LENGTH). 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalsIgnoreCase(SECURE)) { 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index += SECURE_LENGTH; 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.secure = true; 843dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (index == length) break; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == EQUAL) index++; 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "httponly" is a known attribute doesn't use "="; 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while sites like live.com uses "httponly=" 850dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (length - index >= HTTP_ONLY_LENGTH 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieString.substring(index, 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index + HTTP_ONLY_LENGTH). 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalsIgnoreCase(HTTP_ONLY)) { 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index += HTTP_ONLY_LENGTH; 855dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (index == length) break; 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == EQUAL) index++; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME: currently only parse the attribute 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalIndex = cookieString.indexOf(EQUAL, index); 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (equalIndex > 0) { 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = cookieString.substring(index, equalIndex) 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .toLowerCase(); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals(EXPIRES)) { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int comaIndex = cookieString.indexOf(COMMA, equalIndex); 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip ',' in (Wdy, DD-Mon-YYYY HH:MM:SS GMT) or 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (Weekday, DD-Mon-YY HH:MM:SS GMT) if it applies. 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "Wednesday" is the longest Weekday which has length 9 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((comaIndex != -1) && 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (comaIndex - equalIndex <= 10)) { 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = comaIndex + 1; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project semicolonIndex = cookieString.indexOf(SEMICOLON, index); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int commaIndex = cookieString.indexOf(COMMA, index); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (semicolonIndex == -1 && commaIndex == -1) { 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = length; 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (semicolonIndex == -1) { 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = commaIndex; 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (commaIndex == -1) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = semicolonIndex; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = Math.min(semicolonIndex, commaIndex); 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value = 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieString.substring(equalIndex + 1, index); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strip quotes if they exist 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 2 && value.charAt(0) == QUOTATION) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int endQuote = value.indexOf(QUOTATION, 1); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endQuote > 0) { 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.substring(1, endQuote); 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals(EXPIRES)) { 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.expires = HttpDateTime.parse(value); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalArgumentException ex) { 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "illegal format for expires: " + value); 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(MAX_AGE)) { 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.expires = System.currentTimeMillis() + 1000 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Long.parseLong(value); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "illegal format for max-age: " + value); 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(PATH)) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only allow non-empty path value 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 0) { 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.path = value; 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(DOMAIN)) { 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastPeriod = value.lastIndexOf(PERIOD); 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPeriod == 0) { 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // disallow cookies set for TLDs like [.com] 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer.parseInt(value.substring(lastPeriod + 1)); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no wildcard for ip address match 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!value.equals(host)) { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no cross-site cookie 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore the exception, value is a host name 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.toLowerCase(); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.charAt(0) != PERIOD) { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pre-pended dot to make it as a domain cookie 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = PERIOD + value; 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastPeriod++; 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (host.endsWith(value.substring(1))) { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = value.length(); 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hostLen = host.length(); 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostLen > (len - 1) 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && host.charAt(hostLen - len) != PERIOD) { 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure the bar.com doesn't match .ar.com 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // disallow cookies set on ccTLDs like [.co.uk] 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((len == lastPeriod + 3) 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (len >= 6 && len <= 8)) { 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = value.substring(1, lastPeriod); 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Arrays.binarySearch(BAD_COUNTRY_2LDS, s) >= 0) { 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = value; 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no cross-site or more specific sub-domain cookie 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bad format, force return 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = length; 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie != null && cookie.domain != null) { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.add(cookie); 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 976