CookieSyncManager.java revision 74008f608af0c567456d37e63d48643689388c74
1/*
2 * Copyright (C) 2007 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.content.Context;
20import android.util.Log;
21import android.webkit.CookieManager.Cookie;
22
23import java.util.ArrayList;
24import java.util.Iterator;
25
26/**
27 * The CookieSyncManager is used to synchronize the browser cookie store
28 * between RAM and permanent storage. To get the best performance, browser cookies are
29 * saved in RAM. A separate thread saves the cookies between, driven by a timer.
30 * <p>
31 *
32 * To use the CookieSyncManager, the host application has to call the following
33 * when the application starts:
34 * <p>
35 *
36 * <pre class="prettyprint">CookieSyncManager.createInstance(context)</pre><p>
37 *
38 * To set up for sync, the host application has to call<p>
39 * <pre class="prettyprint">CookieSyncManager.getInstance().startSync()</pre><p>
40 *
41 * in Activity.onResume(), and call
42 * <p>
43 *
44 * <pre class="prettyprint">
45 * CookieSyncManager.getInstance().stopSync()
46 * </pre><p>
47 *
48 * in Activity.onPause().<p>
49 *
50 * To get instant sync instead of waiting for the timer to trigger, the host can
51 * call
52 * <p>
53 * <pre class="prettyprint">CookieSyncManager.getInstance().sync()</pre><p>
54 *
55 * The sync interval is 5 minutes, so you will want to force syncs
56 * manually anyway, for instance in {@link
57 * WebViewClient#onPageFinished}. Note that even sync() happens
58 * asynchronously, so don't do it just as your activity is shutting
59 * down.
60 */
61public final class CookieSyncManager extends WebSyncManager {
62
63    private static CookieSyncManager sRef;
64
65    // time when last update happened
66    private long mLastUpdate;
67
68    private CookieSyncManager(Context context) {
69        super(context, "CookieSyncManager");
70    }
71
72    /**
73     * Singleton access to a {@link CookieSyncManager}. An
74     * IllegalStateException will be thrown if
75     * {@link CookieSyncManager#createInstance(Context)} is not called before.
76     *
77     * @return CookieSyncManager
78     */
79    public static synchronized CookieSyncManager getInstance() {
80        if (sRef == null) {
81            throw new IllegalStateException(
82                    "CookieSyncManager::createInstance() needs to be called "
83                            + "before CookieSyncManager::getInstance()");
84        }
85        return sRef;
86    }
87
88    /**
89     * Create a singleton CookieSyncManager within a context
90     * @param context
91     * @return CookieSyncManager
92     */
93    public static synchronized CookieSyncManager createInstance(
94            Context context) {
95        if (sRef == null) {
96            sRef = new CookieSyncManager(context);
97        }
98        return sRef;
99    }
100
101    /**
102     * Package level api, called from CookieManager. Get all the cookies which
103     * matches a given base domain.
104     * @param domain
105     * @return A list of Cookie
106     */
107    ArrayList<Cookie> getCookiesForDomain(String domain) {
108        // null mDataBase implies that the host application doesn't support
109        // persistent cookie. No sync needed.
110        if (mDataBase == null) {
111            return new ArrayList<Cookie>();
112        }
113
114        return mDataBase.getCookiesForDomain(domain);
115    }
116
117    /**
118     * Package level api, called from CookieManager Clear all cookies in the
119     * database
120     */
121    void clearAllCookies() {
122        // null mDataBase implies that the host application doesn't support
123        // persistent cookie.
124        if (mDataBase == null) {
125            return;
126        }
127
128        mDataBase.clearCookies();
129    }
130
131    /**
132     * Returns true if there are any saved cookies.
133     */
134    boolean hasCookies() {
135        // null mDataBase implies that the host application doesn't support
136        // persistent cookie.
137        if (mDataBase == null) {
138            return false;
139        }
140
141        return mDataBase.hasCookies();
142    }
143
144    /**
145     * Package level api, called from CookieManager Clear all session cookies in
146     * the database
147     */
148    void clearSessionCookies() {
149        // null mDataBase implies that the host application doesn't support
150        // persistent cookie.
151        if (mDataBase == null) {
152            return;
153        }
154
155        mDataBase.clearSessionCookies();
156    }
157
158    /**
159     * Package level api, called from CookieManager Clear all expired cookies in
160     * the database
161     */
162    void clearExpiredCookies(long now) {
163        // null mDataBase implies that the host application doesn't support
164        // persistent cookie.
165        if (mDataBase == null) {
166            return;
167        }
168
169        mDataBase.clearExpiredCookies(now);
170    }
171
172    protected void syncFromRamToFlash() {
173        if (WebView.LOGV_ENABLED) {
174            Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash STARTS");
175        }
176
177        if (!CookieManager.getInstance().acceptCookie()) {
178            return;
179        }
180
181        ArrayList<Cookie> cookieList = CookieManager.getInstance()
182                .getUpdatedCookiesSince(mLastUpdate);
183        mLastUpdate = System.currentTimeMillis();
184        syncFromRamToFlash(cookieList);
185
186        ArrayList<Cookie> lruList =
187                CookieManager.getInstance().deleteLRUDomain();
188        syncFromRamToFlash(lruList);
189
190        if (WebView.LOGV_ENABLED) {
191            Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash DONE");
192        }
193    }
194
195    private void syncFromRamToFlash(ArrayList<Cookie> list) {
196        Iterator<Cookie> iter = list.iterator();
197        while (iter.hasNext()) {
198            Cookie cookie = iter.next();
199            if (cookie.mode != Cookie.MODE_NORMAL) {
200                if (cookie.mode != Cookie.MODE_NEW) {
201                    mDataBase.deleteCookies(cookie.domain, cookie.path,
202                            cookie.name);
203                }
204                if (cookie.mode != Cookie.MODE_DELETED) {
205                    mDataBase.addCookie(cookie);
206                    CookieManager.getInstance().syncedACookie(cookie);
207                } else {
208                    CookieManager.getInstance().deleteACookie(cookie);
209                }
210            }
211        }
212    }
213}
214