1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
19import android.net.ParseException;
20import android.net.WebAddress;
21import android.os.AsyncTask;
22import android.util.Log;
23
24class CookieManagerClassic extends CookieManager {
25
26    private static CookieManagerClassic sRef;
27
28    private static final String LOGTAG = "webkit";
29
30    private int mPendingCookieOperations = 0;
31
32    private CookieManagerClassic() {
33    }
34
35    public static synchronized CookieManagerClassic getInstance() {
36        if (sRef == null) {
37            sRef = new CookieManagerClassic();
38        }
39        return sRef;
40    }
41
42    @Override
43    public synchronized void setAcceptCookie(boolean accept) {
44        nativeSetAcceptCookie(accept);
45    }
46
47    @Override
48    public synchronized boolean acceptCookie() {
49        return nativeAcceptCookie();
50    }
51
52    @Override
53    public void setCookie(String url, String value) {
54        setCookie(url, value, false);
55    }
56
57    /**
58     * See {@link #setCookie(String, String)}
59     * @param url The URL for which the cookie is set
60     * @param value The value of the cookie, as a string, using the format of
61     *              the 'Set-Cookie' HTTP response header
62     * @param privateBrowsing Whether to use the private browsing cookie jar
63     */
64    void setCookie(String url, String value, boolean privateBrowsing) {
65        WebAddress uri;
66        try {
67            uri = new WebAddress(url);
68        } catch (ParseException ex) {
69            Log.e(LOGTAG, "Bad address: " + url);
70            return;
71        }
72
73        nativeSetCookie(uri.toString(), value, privateBrowsing);
74    }
75
76    @Override
77    public String getCookie(String url) {
78        return getCookie(url, false);
79    }
80
81    @Override
82    public String getCookie(String url, boolean privateBrowsing) {
83        WebAddress uri;
84        try {
85            uri = new WebAddress(url);
86        } catch (ParseException ex) {
87            Log.e(LOGTAG, "Bad address: " + url);
88            return null;
89        }
90
91        return nativeGetCookie(uri.toString(), privateBrowsing);
92    }
93
94    @Override
95    public synchronized String getCookie(WebAddress uri) {
96        return nativeGetCookie(uri.toString(), false);
97    }
98
99    /**
100     * Waits for pending operations to completed.
101     */
102    void waitForCookieOperationsToComplete() {
103        // Note that this function is applicable for both the java
104        // and native http stacks, and works correctly with either.
105        synchronized (this) {
106            while (mPendingCookieOperations > 0) {
107                try {
108                    wait();
109                } catch (InterruptedException e) { }
110            }
111        }
112    }
113
114    private synchronized void signalCookieOperationsComplete() {
115        mPendingCookieOperations--;
116        assert mPendingCookieOperations > -1;
117        notify();
118    }
119
120    private synchronized void signalCookieOperationsStart() {
121        mPendingCookieOperations++;
122    }
123
124    @Override
125    public void removeSessionCookie() {
126        signalCookieOperationsStart();
127        new AsyncTask<Void, Void, Void>() {
128            @Override
129            protected Void doInBackground(Void... none) {
130                nativeRemoveSessionCookie();
131                signalCookieOperationsComplete();
132                return null;
133            }
134        }.execute();
135    }
136
137    @Override
138    public void removeAllCookie() {
139        nativeRemoveAllCookie();
140    }
141
142    @Override
143    public synchronized boolean hasCookies() {
144        return hasCookies(false);
145    }
146
147    @Override
148    public synchronized boolean hasCookies(boolean privateBrowsing) {
149        return nativeHasCookies(privateBrowsing);
150    }
151
152    @Override
153    public void removeExpiredCookie() {
154        nativeRemoveExpiredCookie();
155    }
156
157    @Override
158    protected void flushCookieStore() {
159        nativeFlushCookieStore();
160    }
161
162    @Override
163    protected boolean allowFileSchemeCookiesImpl() {
164        return nativeAcceptFileSchemeCookies();
165    }
166
167    @Override
168    protected void setAcceptFileSchemeCookiesImpl(boolean accept) {
169        nativeSetAcceptFileSchemeCookies(accept);
170    }
171
172    // Native functions
173    private static native boolean nativeAcceptCookie();
174    private static native String nativeGetCookie(String url, boolean privateBrowsing);
175    private static native boolean nativeHasCookies(boolean privateBrowsing);
176    private static native void nativeRemoveAllCookie();
177    private static native void nativeRemoveExpiredCookie();
178    private static native void nativeRemoveSessionCookie();
179    private static native void nativeSetAcceptCookie(boolean accept);
180    private static native void nativeSetCookie(String url, String value, boolean privateBrowsing);
181    private static native void nativeFlushCookieStore();
182    private static native boolean nativeAcceptFileSchemeCookies();
183    private static native void nativeSetAcceptFileSchemeCookies(boolean accept);
184}
185