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