CookieManager.java revision 06312cae6b0e00c4ccbe84e9c682de8d607897a9
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; 212269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport android.net.http.HttpDateTime; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 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) { 1536a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // An exact match means that domain, path, and name are equal. If 1546a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // both values are null, the cookies match. If both values are 1556a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // non-null, the cookies match. If one value is null and the other 1566a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // is non-null, the cookies do not match (i.e. "foo=;" and "foo;") 1576a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott boolean valuesMatch = !((value == null) ^ (in.value == null)); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return domain.equals(in.domain) && path.equals(in.path) && 1596a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott name.equals(in.name) && valuesMatch; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean domainMatch(String urlHost) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (domain.startsWith(".")) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlHost.endsWith(domain.substring(1))) { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = domain.length(); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int urlLen = urlHost.length(); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlLen > len - 1) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure bar.com doesn't match .ar.com 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlHost.charAt(urlLen - len) == PERIOD; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // exact match if domain is not leading w/ dot 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlHost.equals(domain); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean pathMatch(String urlPath) { 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (urlPath.startsWith(path)) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = path.length(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(LOGTAG, "Empty cookie path"); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int urlLen = urlPath.length(); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path.charAt(len-1) != PATH_DELIM && urlLen > len) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure /wee doesn't match /we 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return urlPath.charAt(len) == PATH_DELIM; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "domain: " + domain + "; path: " + path + "; name: " + name 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "; value: " + value; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 203f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba private static final CookieComparator COMPARATOR = new CookieComparator(); 204f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 205f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba private static final class CookieComparator implements Comparator<Cookie> { 206f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba public int compare(Cookie cookie1, Cookie cookie2) { 2078ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // According to RFC 2109, multiple cookies are ordered in a way such 2088ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // that those with more specific Path attributes precede those with 2098ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // less specific. Ordering with respect to other attributes (e.g., 2108ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // Domain) is unspecified. 2118ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // As Set is not modified if the two objects are same, we do want to 2128ae277735439940480e1301ff729cee32c2ab72eGrace Kloba // assign different value for each cookie. 2138ae277735439940480e1301ff729cee32c2ab72eGrace Kloba int diff = cookie2.path.length() - cookie1.path.length(); 2146a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (diff != 0) return diff; 2156a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 2166a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott diff = cookie2.domain.length() - cookie1.domain.length(); 2176a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (diff != 0) return diff; 2186a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 2196a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // If cookie2 has a null value, it should come later in 2206a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // the list. 2216a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (cookie2.value == null) { 2222807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott // If both cookies have null values, fall back to using the name 2232807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott // difference. 2242807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott if (cookie1.value != null) { 2252807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott return -1; 2262807dbd5942a64eb0200de3c2ea0f551a22720f3Patrick Scott } 2276a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } else if (cookie1.value == null) { 2286a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Now we know that cookie2 does not have a null value, if 2296a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // cookie1 has a null value, place it later in the list. 2306a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott return 1; 2318ae277735439940480e1301ff729cee32c2ab72eGrace Kloba } 2326a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 23306312cae6b0e00c4ccbe84e9c682de8d607897a9Patrick Scott // Fallback to comparing the name to ensure consistent order. 23406312cae6b0e00c4ccbe84e9c682de8d607897a9Patrick Scott return cookie1.name.compareTo(cookie2.name); 235f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 236f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 237f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CookieManager() { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Object clone() throws CloneNotSupportedException { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new CloneNotSupportedException("doesn't implement Cloneable"); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a singleton CookieManager. If this is called before any 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link WebView} is created or outside of {@link WebView} context, the 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller needs to call {@link CookieSyncManager#createInstance(Context)} 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * first. 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return CookieManager 25206312cae6b0e00c4ccbe84e9c682de8d607897a9Patrick Scott */ 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static synchronized CookieManager getInstance() { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sRef == null) { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRef = new CookieManager(); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sRef; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Control whether cookie is enabled or disabled 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param accept TRUE if accept cookie 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setAcceptCookie(boolean accept) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAcceptCookie = accept; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return whether cookie is enabled 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return TRUE if accept cookie 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean acceptCookie() { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAcceptCookie; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set cookie for a given url. The old cookie with same host/path/name will 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be removed. The new cookie will be added if it is not expired or it does 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have expiration which implies it is session cookie. 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url The url which cookie is set for 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value for set-cookie: in http response header 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCookie(String url, String value) { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WebAddress uri; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = new WebAddress(url); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ParseException ex) { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "Bad address: " + url); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCookie(uri, value); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set cookie for a given uri. The old cookie with same host/path/name will 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be removed. The new cookie will be added if it is not expired or it does 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have expiration which implies it is session cookie. 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The uri which cookie is set for 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value for set-cookie: in http response header 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide - hide this because it takes in a parameter of type WebAddress, 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a system private class. 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setCookie(WebAddress uri, String value) { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value != null && value.length() > MAX_COOKIE_LENGTH) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAcceptCookie || uri == null) { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3102e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] hostAndPath = getHostAndPath(uri); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath == null) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For default path, when setting a cookie, the spec says: 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //Path: Defaults to the path of the request URL that generated the 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set-Cookie response, up to, but not including, the 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // right-most /. 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath[1].length() > 1) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = hostAndPath[1].lastIndexOf(PATH_DELIM); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hostAndPath[1] = hostAndPath[1].substring(0, 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index > 0 ? index : index + 1); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookies = null; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookies = parseCookie(hostAndPath[0], hostAndPath[1], value); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException ex) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "parse cookie failed for: " + value); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookies == null || cookies.size() == 0) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(hostAndPath[0]); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList == null) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList = CookieSyncManager.getInstance() 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getCookiesForDomain(baseDomain); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.put(baseDomain, cookieList); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = cookies.size(); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = cookies.get(i); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean done = false; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = cookieList.iterator(); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookieEntry = iter.next(); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.exactMatch(cookieEntry)) { 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires < 0 || cookie.expires > now) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // secure cookies can't be overwritten by non-HTTPS url 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!cookieEntry.secure || HTTPS.equals(uri.mScheme)) { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.value = cookie.value; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.expires = cookie.expires; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.secure = cookie.secure; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastAcessTime = now; 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastUpdateTime = now; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.mode = Cookie.MODE_REPLACED; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.lastUpdateTime = now; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieEntry.mode = Cookie.MODE_DELETED; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project done = true; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise negative means 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // far future 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!done && (cookie.expires < 0 || cookie.expires > now)) { 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastAcessTime = now; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastUpdateTime = now; 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.mode = Cookie.MODE_NEW; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList.size() > MAX_COOKIE_COUNT_PER_BASE_DOMAIN) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie toDelete = new Cookie(); 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete.lastAcessTime = now; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter2 = cookieList.iterator(); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter2.hasNext()) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookieEntry2 = iter2.next(); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((cookieEntry2.lastAcessTime < toDelete.lastAcessTime) 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieEntry2.mode != Cookie.MODE_DELETED) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete = cookieEntry2; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toDelete.mode = Cookie.MODE_DELETED; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList.add(cookie); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get cookie(s) for a given url so that it can be set to "cookie:" in http 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request header. 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url The url needs cookie 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getCookie(String url) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WebAddress uri; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = new WebAddress(url); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ParseException ex) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, "Bad address: " + url); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getCookie(uri); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get cookie(s) for a given uri so that it can be set to "cookie:" in http 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request header. 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The uri needs cookie 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide - hide this because it has a parameter of type WebAddress, which 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is a system private class. 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String getCookie(WebAddress uri) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAcceptCookie || uri == null) { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] hostAndPath = getHostAndPath(uri); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostAndPath == null) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(hostAndPath[0]); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList == null) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList = CookieSyncManager.getInstance() 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getCookiesForDomain(baseDomain); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.put(baseDomain, cookieList); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean secure = HTTPS.equals(uri.mScheme); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = cookieList.iterator(); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 450f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba SortedSet<Cookie> cookieSet = new TreeSet<Cookie>(COMPARATOR); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.domainMatch(hostAndPath[0]) && 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.pathMatch(hostAndPath[1]) 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (cookie.expires < 0 || cookie.expires > now) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (!cookie.secure || secure) 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookie.mode != Cookie.MODE_DELETED) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.lastAcessTime = now; 461f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba cookieSet.add(cookie); 462f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 463f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 465f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba StringBuilder ret = new StringBuilder(256); 466f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba Iterator<Cookie> setIter = cookieSet.iterator(); 467f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba while (setIter.hasNext()) { 468f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba Cookie cookie = setIter.next(); 469f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba if (ret.length() > 0) { 470f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(SEMICOLON); 471f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba // according to RC2109, SEMICOLON is official separator, 472f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba // but when log in yahoo.com, it needs WHITE_SPACE too. 473f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(WHITE_SPACE); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 475f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 476f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba ret.append(cookie.name); 4776a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (cookie.value != null) { 4786a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott ret.append(EQUAL); 4796a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott ret.append(cookie.value); 4806a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 482f4046ba80369efb2d2b75df05dfdf41a07bc8710Grace Kloba 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret.length() > 0) { 4842e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret.toString(); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4892e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "getCookie: uri: " + uri 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " But can't find cookie."); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all session cookies, which are cookies without expiration date 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeSessionCookie() { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires == -1) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iter.remove(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearSessionCookies(); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all cookies 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeAllCookie() { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap = new LinkedHashMap<String, ArrayList<Cookie>>( 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MAX_DOMAIN_COUNT, 0.75f, true); 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearAllCookies(); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return true if there are stored cookies. 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean hasCookies() { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return CookieSyncManager.getInstance().hasCookies(); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all expired cookies 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeExpiredCookie() { 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Runnable clearCache = new Runnable() { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(CookieManager.this) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // expires == -1 means no expires defined. Otherwise 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // negative means far future 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.expires > 0 && cookie.expires < now) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iter.remove(); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieSyncManager.getInstance().clearExpiredCookies(now); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Thread(clearCache).start(); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a list of cookies which are updated since a given time. 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param last The given time in millisec 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of cookies 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized ArrayList<Cookie> getUpdatedCookiesSince(long last) { 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookies = new ArrayList<Cookie>(); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieList = mCookieMap.values(); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieList.iterator(); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext()) { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.lastUpdateTime > last) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookies.add(cookie); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cookies; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete a Cookie in the RAM 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookie Cookie to be deleted 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void deleteACookie(Cookie cookie) { 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie.mode == Cookie.MODE_DELETED) { 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String baseDomain = getBaseDomain(cookie.domain); 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList != null) { 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieList.remove(cookie); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieList.isEmpty()) { 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.remove(baseDomain); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called after a cookie is synced to FLASH 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookie Cookie to be synced 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized void syncedACookie(Cookie cookie) { 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.mode = Cookie.MODE_NORMAL; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package level api, called from CookieSyncManager 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete the least recent used domains if the total cookie count in RAM 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exceeds the limit 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of cookies which are removed from RAM 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized ArrayList<Cookie> deleteLRUDomain() { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int byteCount = 0; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mapSize = mCookieMap.size(); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapSize < MAX_RAM_DOMAIN_COUNT) { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collection<ArrayList<Cookie>> cookieLists = mCookieMap.values(); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator(); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> list = listIter.next(); 6452e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Cookie> iter = list.iterator(); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = iter.next(); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 14 is 3 * sizeof(long) + sizeof(boolean) 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // + sizeof(byte) 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteCount += cookie.domain.length() 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.path.length() 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + cookie.name.length() 6546a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott + (cookie.value != null 6556a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott ? cookie.value.length() 6566a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott : 0) 6576a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott + 14; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += list.size(); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> retlist = new ArrayList<Cookie>(); 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) { 6682e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, count + " cookies used " + byteCount 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " bytes with " + mapSize + " domains"); 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] domains = mCookieMap.keySet().toArray(); 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int toGo = mapSize / 10 + 1; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (toGo-- > 0){ 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String domain = domains[toGo].toString(); 6762e5c150e746647a1ce5c10e1708debbf06c45ea7Derek Sollenberger if (DebugFlags.COOKIE_MANAGER) { 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(LOGTAG, "delete domain: " + domain 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " from RAM cache"); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retlist.addAll(mCookieMap.get(domain)); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCookieMap.remove(domain); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retlist; 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extract the host and path out of a uri 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The given WebAddress 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The host and path in the format of String[], String[0] is host 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which has at least two periods, String[1] is path which always 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ended with "/" 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] getHostAndPath(WebAddress uri) { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri.mHost != null && uri.mPath != null) { 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] ret = new String[2]; 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = uri.mHost; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[1] = uri.mPath; 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = ret[0].indexOf(PERIOD); 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == -1) { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri.mScheme.equalsIgnoreCase("file")) { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // There is a potential bug where a local file path matches 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // another file in the local web server directory. Still 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "localhost" is the best pseudo domain name. 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = "localhost"; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (index == ret[0].lastIndexOf(PERIOD)) { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cookie host must have at least two periods 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = PERIOD + ret[0]; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret[1].charAt(0) != PATH_DELIM) { 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * find cookie path, e.g. for http://www.google.com, the path is "/" 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab/, the path is "/lab" 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab/foo, the path is "/lab/foo" 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab?hl=en, the path is "/lab" 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for http://www.google.com/lab.asp?hl=en, the path is "/lab.asp" 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: the path from URI has at least one "/" 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See: 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.unix.com.ua/rfc/rfc2109.html 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = ret[1].indexOf(QUESTION_MARK); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index != -1) { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[1] = ret[1].substring(0, index); 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the base domain for a give host. E.g. mail.google.com will return 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * google.com 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param host The give host 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the base domain 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getBaseDomain(String host) { 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startIndex = 0; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextIndex = host.indexOf(PERIOD); 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastIndex = host.lastIndexOf(PERIOD); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextIndex < lastIndex) { 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startIndex = nextIndex + 1; 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextIndex = host.indexOf(PERIOD, startIndex); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startIndex > 0) { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return host.substring(startIndex); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return host; 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parseCookie() parses the cookieString which is a comma-separated list of 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one or more cookies in the format of "NAME=VALUE; expires=DATE; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * path=PATH; domain=DOMAIN_NAME; secure httponly" to a list of Cookies. 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Here is a sample: IGDND=1, IGPC=ET=UB8TSNwtDmQ:AF=0; expires=Sun, 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 17-Jan-2038 19:14:07 GMT; path=/ig; domain=.google.com, =, 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PREF=ID=408909b1b304593d:TM=1156459854:LM=1156459854:S=V-vCAU6Sh-gobCfO; 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com which 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * contains 3 cookies IGDND, IGPC, PREF and an empty cookie 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param host The default host 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The default path 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cookieString The string coming from "Set-Cookie:" 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of Cookies 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<Cookie> parseCookie(String host, String path, 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String cookieString) { 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Cookie> ret = new ArrayList<Cookie>(); 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = cookieString.length(); 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cookie cookie = null; 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // done 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= length) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip white space 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == WHITE_SPACE) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * get NAME=VALUE; pair. detecting the end of a pair is tricky, it 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can be the end of a string, like "foo=bluh", it can be semicolon 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * like "foo=bluh;path=/"; or it can be enclosed by \", like 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "foo=\"bluh bluh\";path=/" 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it as one cookie instead of two cookies. 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 800ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int semicolonIndex = cookieString.indexOf(SEMICOLON, index); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int equalIndex = cookieString.indexOf(EQUAL, index); 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie = new Cookie(host, path); 8036a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott 8046a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Cookies like "testcookie; path=/;" are valid and used 805d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // (lovefilm.se). 806d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // Look for 2 cases: 807d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // 1. "foo" or "foo;" where equalIndex is -1 808d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // 2. "foo; path=..." where the first semicolon is before an equal 809d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // and a semicolon exists. 810d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott if ((semicolonIndex != -1 && (semicolonIndex < equalIndex)) || 811d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott equalIndex == -1) { 8126a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Fix up the index in case we have a string like "testcookie" 8136a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (semicolonIndex == -1) { 8146a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex = length; 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8166a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.name = cookieString.substring(index, semicolonIndex); 8176a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = null; 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8196a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.name = cookieString.substring(index, equalIndex); 820d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // Make sure we do not throw an exception if the cookie is like 821d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // "foo=" 822d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott if ((equalIndex < length - 1) && 823d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott (cookieString.charAt(equalIndex + 1) == QUOTATION)) { 8246a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott index = cookieString.indexOf(QUOTATION, equalIndex + 2); 8256a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (index == -1) { 8266a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // bad format, force return 8276a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott break; 8286a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 8296a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 8306a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // Get the semicolon index again in case it was contained within 8316a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // the quotations. 8326a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex = cookieString.indexOf(SEMICOLON, index); 8336a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (semicolonIndex == -1) { 8346a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex = length; 8356a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 8366a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott if (semicolonIndex - equalIndex > MAX_COOKIE_LENGTH) { 8376a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott // cookie is too big, trim it 8386a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = cookieString.substring(equalIndex + 1, 8396a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott equalIndex + 1 + MAX_COOKIE_LENGTH); 8406a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } else if (equalIndex + 1 == semicolonIndex 8416a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott || semicolonIndex < equalIndex) { 842d2b49d931afd22051807ef8919437ee889211bbbPatrick Scott // this is an unusual case like "foo=;" or "foo=" 8436a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = ""; 8446a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } else { 8456a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott cookie.value = cookieString.substring(equalIndex + 1, 8466a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott semicolonIndex); 8476a4472f4d5513a69665811115c56f63e5f3935fePatrick Scott } 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get attributes 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = semicolonIndex; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // done 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= length) { 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip white space and semicolon 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == WHITE_SPACE 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || cookieString.charAt(index) == SEMICOLON) { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // comma means next cookie 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == COMMA) { 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index++; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "secure" is a known attribute doesn't use "="; 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while sites like live.com uses "secure=" 872dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (length - index >= SECURE_LENGTH 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieString.substring(index, index + SECURE_LENGTH). 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalsIgnoreCase(SECURE)) { 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index += SECURE_LENGTH; 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.secure = true; 877dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (index == length) break; 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == EQUAL) index++; 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "httponly" is a known attribute doesn't use "="; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while sites like live.com uses "httponly=" 884dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (length - index >= HTTP_ONLY_LENGTH 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && cookieString.substring(index, 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index + HTTP_ONLY_LENGTH). 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalsIgnoreCase(HTTP_ONLY)) { 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index += HTTP_ONLY_LENGTH; 889dbdad99813be49f2a64b876507ae18db42db7bbcGrace Kloba if (index == length) break; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookieString.charAt(index) == EQUAL) index++; 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME: currently only parse the attribute 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalIndex = cookieString.indexOf(EQUAL, index); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (equalIndex > 0) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = cookieString.substring(index, equalIndex) 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .toLowerCase(); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals(EXPIRES)) { 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int comaIndex = cookieString.indexOf(COMMA, equalIndex); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // skip ',' in (Wdy, DD-Mon-YYYY HH:MM:SS GMT) or 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (Weekday, DD-Mon-YY HH:MM:SS GMT) if it applies. 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // "Wednesday" is the longest Weekday which has length 9 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((comaIndex != -1) && 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (comaIndex - equalIndex <= 10)) { 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = comaIndex + 1; 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project semicolonIndex = cookieString.indexOf(SEMICOLON, index); 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int commaIndex = cookieString.indexOf(COMMA, index); 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (semicolonIndex == -1 && commaIndex == -1) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = length; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (semicolonIndex == -1) { 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = commaIndex; 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (commaIndex == -1) { 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = semicolonIndex; 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = Math.min(semicolonIndex, commaIndex); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value = 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookieString.substring(equalIndex + 1, index); 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strip quotes if they exist 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 2 && value.charAt(0) == QUOTATION) { 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int endQuote = value.indexOf(QUOTATION, 1); 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endQuote > 0) { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.substring(1, endQuote); 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals(EXPIRES)) { 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.expires = HttpDateTime.parse(value); 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalArgumentException ex) { 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "illegal format for expires: " + value); 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(MAX_AGE)) { 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.expires = System.currentTimeMillis() + 1000 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Long.parseLong(value); 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(LOGTAG, 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "illegal format for max-age: " + value); 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(PATH)) { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only allow non-empty path value 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 0) { 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.path = value; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals(DOMAIN)) { 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastPeriod = value.lastIndexOf(PERIOD); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPeriod == 0) { 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // disallow cookies set for TLDs like [.com] 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer.parseInt(value.substring(lastPeriod + 1)); 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no wildcard for ip address match 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!value.equals(host)) { 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no cross-site cookie 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore the exception, value is a host name 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.toLowerCase(); 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.charAt(0) != PERIOD) { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pre-pended dot to make it as a domain cookie 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = PERIOD + value; 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastPeriod++; 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (host.endsWith(value.substring(1))) { 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = value.length(); 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hostLen = host.length(); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hostLen > (len - 1) 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && host.charAt(hostLen - len) != PERIOD) { 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure the bar.com doesn't match .ar.com 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // disallow cookies set on ccTLDs like [.co.uk] 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((len == lastPeriod + 3) 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (len >= 6 && len <= 8)) { 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = value.substring(1, lastPeriod); 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Arrays.binarySearch(BAD_COUNTRY_2LDS, s) >= 0) { 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = value; 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no cross-site or more specific sub-domain cookie 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cookie.domain = null; 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bad format, force return 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = length; 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cookie != null && cookie.domain != null) { 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.add(cookie); 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1010