151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.net;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
297363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamathimport dalvik.system.VMRuntime;
307363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ArrayList;
32225d1301a97641464a1b437219eb60853260b28cNarayan Kamathimport java.util.Collections;
337363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamathimport java.util.HashMap;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Iterator;
357363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamathimport java.util.List;
367363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamathimport java.util.Map;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.locks.ReentrantLock;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A simple in-memory java.net.CookieStore implementation
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Edward Wang
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.6
447363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath * @hide Visible for testing only.
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
467363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamathpublic class InMemoryCookieStore implements CookieStore {
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the in-memory representation of cookies
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map<URI, List<HttpCookie>> uriIndex = null;
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // use ReentrantLock instead of syncronized for scalability
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ReentrantLock lock = null;
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
537363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath    private final boolean applyMCompatibility;
547363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The default ctor
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public InMemoryCookieStore() {
597363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath        this(VMRuntime.getRuntime().getTargetSdkVersion());
607363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath    }
617363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath
627363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath    public InMemoryCookieStore(int targetSdkVersion) {
637363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath        uriIndex = new HashMap<>();
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock = new ReentrantLock(false);
657363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath        applyMCompatibility = (targetSdkVersion <= 23);
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Add one cookie into cookie store.
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void add(URI uri, HttpCookie cookie) {
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // pre-condition : argument can't be null
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cookie == null) {
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("cookie is null");
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
79a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            if (cookie.getMaxAge() != 0) {
80a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                addIndex(uriIndex, getEffectiveURI(uri), cookie);
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get all cookies, which:
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  1) given uri domain-matches with, or, associated with
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     given uri when added to the cookie store.
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  3) not expired.
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * See RFC 2965 sec. 3.3.4 for more detail.
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public List<HttpCookie> get(URI uri) {
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // argument can't be null
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (uri == null) {
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("uri is null");
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List<HttpCookie> cookies = new ArrayList<HttpCookie>();
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // check domainIndex first
1057938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak            getInternal1(cookies, uriIndex, uri.getHost());
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // check uriIndex then
1077938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak            getInternal2(cookies, uriIndex, getEffectiveURI(uri));
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cookies;
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get all cookies in cookie store, except those have expired
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public List<HttpCookie> getCookies() {
119a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak        List<HttpCookie> rt = new ArrayList<HttpCookie>();
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
123a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            for (List<HttpCookie> list : uriIndex.values()) {
124a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                Iterator<HttpCookie> it = list.iterator();
125a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                while (it.hasNext()) {
126a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    HttpCookie cookie = it.next();
127a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    if (cookie.hasExpired()) {
128a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                        it.remove();
129a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    } else if (!rt.contains(cookie)) {
130a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                        rt.add(cookie);
131a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    }
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
135a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            rt = Collections.unmodifiableList(rt);
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return rt;
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get all URIs, which are associated with at least one cookie
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * of this cookie store.
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public List<URI> getURIs() {
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List<URI> uris = new ArrayList<URI>();
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
151a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            List<URI> result = new ArrayList<URI>(uriIndex.keySet());
152a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            result.remove(null);
153a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            return Collections.unmodifiableList(result);
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            uris.addAll(uriIndex.keySet());
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Remove a cookie from store
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean remove(URI uri, HttpCookie ck) {
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // argument can't be null
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ck == null) {
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("cookie is null");
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
172a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            uri = getEffectiveURI(uri);
1739f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            if (uriIndex.get(uri) == null) {
174a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                return false;
1755a7bc45f8f662d0673779aad34fc595309d93526Przemyslaw Szczepaniak            } else {
176a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                List<HttpCookie> cookies = uriIndex.get(uri);
177a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                if (cookies != null) {
178a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    return cookies.remove(ck);
179a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                } else {
180a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    return false;
181a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                }
1825a7bc45f8f662d0673779aad34fc595309d93526Przemyslaw Szczepaniak            }
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Remove all cookies in this cookie store.
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean removeAll() {
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
1945a7bc45f8f662d0673779aad34fc595309d93526Przemyslaw Szczepaniak        boolean result = false;
1955a7bc45f8f662d0673779aad34fc595309d93526Przemyslaw Szczepaniak
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
197a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            result = !uriIndex.isEmpty();
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            uriIndex.clear();
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2035a7bc45f8f662d0673779aad34fc595309d93526Przemyslaw Szczepaniak        return result;
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* ---------------- Private operations -------------- */
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This is almost the same as HttpCookie.domainMatches except for
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * one difference: It won't reject cookies when the 'H' part of the
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * domain contains a dot ('.').
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and the cookie domain is .domain.com, then it should be rejected.
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * However that's not how the real world works. Browsers don't reject and
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * some sites, like yahoo.com do actually expect these cookies to be
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * passed along.
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * And should be used for 'old' style cookies (aka Netscape type of cookies)
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean netscapeDomainMatches(String domain, String host)
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (domain == null || host == null) {
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if there's no embedded dot in domain and domain is not .local
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int embeddedDotInDomain = domain.indexOf('.');
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (embeddedDotInDomain == 0) {
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            embeddedDotInDomain = domain.indexOf('.', 1);
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if the host name contains no dot and the domain name is .local
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int firstDotInHost = host.indexOf('.');
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (firstDotInHost == -1 && isLocalDomain) {
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int domainLength = domain.length();
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lengthDiff = host.length() - domainLength;
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (lengthDiff == 0) {
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // if the host name and the domain name are just string-compare euqal
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return host.equalsIgnoreCase(domain);
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (lengthDiff > 0) {
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // need to check H & D component
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String D = host.substring(lengthDiff);
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2527363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath            // Android M and earlier: Cookies with domain "foo.com" would not match "bar.foo.com".
2537363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath            // The RFC dictates that the user agent must treat those domains as if they had a
2547363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath            // leading period and must therefore match "bar.foo.com".
2557363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath            if (applyMCompatibility && !domain.startsWith(".")) {
2567363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath                return false;
2577363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath            }
2587363410d6ab95420d62cc5e2ee52801a693781ebNarayan Kamath
259225d1301a97641464a1b437219eb60853260b28cNarayan Kamath            return (D.equalsIgnoreCase(domain));
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (lengthDiff == -1) {
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // if domain is actually .host
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (domain.charAt(0) == '.' &&
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    host.equalsIgnoreCase(domain.substring(1)));
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
269a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak    private void getInternal1(List<HttpCookie> cookies, Map<URI, List<HttpCookie>> cookieIndex,
2707938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak            String host) {
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Use a separate list to handle cookies that need to be removed so
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // that there is no conflict with iterators.
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
274a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak        for (Map.Entry<URI, List<HttpCookie>> entry : cookieIndex.entrySet()) {
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<HttpCookie> lst = entry.getValue();
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (HttpCookie c : lst) {
277a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                String domain = c.getDomain();
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
280a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak
281a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    // the cookie still in main cookie store
282a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                    if (!c.hasExpired()) {
2837938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak                        // don't add twice
2847938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak                        if (!cookies.contains(c)) {
285a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                            cookies.add(c);
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        toRemove.add(c);
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Clear up the cookies that need to be removed
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (HttpCookie c : toRemove) {
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                lst.remove(c);
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            toRemove.clear();
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param cookies           [OUT] contains the found cookies
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param cookieIndex       the index
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param comparator        the prediction to decide whether or not
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //                          a cookie in index should be returned
3059f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath    private <T extends Comparable<T>>
3069f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        void getInternal2(List<HttpCookie> cookies, Map<T, List<HttpCookie>> cookieIndex,
3077938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak                          T comparator)
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
309a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak        // Removed cookieJar
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (T index : cookieIndex.keySet()) {
3119f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            if ((index == comparator) || (index != null && comparator.compareTo(index) == 0)) {
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                List<HttpCookie> indexedCookies = cookieIndex.get(index);
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // check the list of cookies associated with this domain
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (indexedCookies != null) {
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Iterator<HttpCookie> it = indexedCookies.iterator();
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    while (it.hasNext()) {
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        HttpCookie ck = it.next();
318a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                        // the cookie still in main cookie store
319a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                        if (!ck.hasExpired()) {
320a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                            // don't add twice
3217938429403c009accb92834db70288110b017115Przemyslaw Szczepaniak                            if (!cookies.contains(ck))
322a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak                                cookies.add(ck);
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            it.remove();
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } // end of indexedCookies != null
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } // end of comparator.compareTo(index) == 0
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } // end of cookieIndex iteration
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // add 'cookie' indexed by 'index' into 'indexStore'
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              T index,
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              HttpCookie cookie)
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
3379f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        // Android-changed : "index" can be null. We only use the URI based
3389f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        // index on Android and we want to support null URIs. The underlying
3399f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        // store is a HashMap which will support null keys anyway.
3409f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        List<HttpCookie> cookies = indexStore.get(index);
3419f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        if (cookies != null) {
3429f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            // there may already have the same cookie, so remove it first
3439f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            cookies.remove(cookie);
3449f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath
3459f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            cookies.add(cookie);
3469f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath        } else {
3479f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            cookies = new ArrayList<HttpCookie>();
3489f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            cookies.add(cookie);
3499f7cb9dbab95a1c94864063908d213487d17535eNarayan Kamath            indexStore.put(index, cookies);
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // for cookie purpose, the effective uri should only be http://host
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the path will be taken into account when path-match algorithm applied
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private URI getEffectiveURI(URI uri) {
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        URI effectiveURI = null;
360a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak        if (uri == null) {
361a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak            return null;
362a5f1c8ef223a10b956f259d60f715d99ac4f04efPrzemyslaw Szczepaniak        }
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            effectiveURI = new URI("http",
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   uri.getHost(),
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   null,  // path component
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   null,  // query component
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   null   // fragment component
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                  );
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (URISyntaxException ignored) {
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            effectiveURI = uri;
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return effectiveURI;
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
377