CookieSyncManager.java revision d89a30af1f37317a51088a207dda865a2f60c83a
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 checkInstanceIsCreated(); 81 return sRef; 82 } 83 84 /** 85 * Create a singleton CookieSyncManager within a context 86 * @param context 87 * @return CookieSyncManager 88 */ 89 public static synchronized CookieSyncManager createInstance( 90 Context context) { 91 JniUtil.setContext(context); 92 Context appContext = context.getApplicationContext(); 93 if (sRef == null) { 94 sRef = new CookieSyncManager(appContext); 95 } 96 return sRef; 97 } 98 99 /** 100 * Package level api, called from CookieManager. Get all the cookies which 101 * matches a given base domain. 102 * @param domain 103 * @return A list of Cookie 104 */ 105 ArrayList<Cookie> getCookiesForDomain(String domain) { 106 // null mDataBase implies that the host application doesn't support 107 // persistent cookie. No sync needed. 108 if (mDataBase == null) { 109 return new ArrayList<Cookie>(); 110 } 111 112 return mDataBase.getCookiesForDomain(domain); 113 } 114 115 /** 116 * Package level api, called from CookieManager Clear all cookies in the 117 * database 118 */ 119 void clearAllCookies() { 120 // null mDataBase implies that the host application doesn't support 121 // persistent cookie. 122 if (mDataBase == null) { 123 return; 124 } 125 126 mDataBase.clearCookies(); 127 } 128 129 /** 130 * Returns true if there are any saved cookies. 131 */ 132 boolean hasCookies() { 133 // null mDataBase implies that the host application doesn't support 134 // persistent cookie. 135 if (mDataBase == null) { 136 return false; 137 } 138 139 return mDataBase.hasCookies(); 140 } 141 142 /** 143 * Package level api, called from CookieManager Clear all session cookies in 144 * the database 145 */ 146 void clearSessionCookies() { 147 // null mDataBase implies that the host application doesn't support 148 // persistent cookie. 149 if (mDataBase == null) { 150 return; 151 } 152 153 mDataBase.clearSessionCookies(); 154 } 155 156 /** 157 * Package level api, called from CookieManager Clear all expired cookies in 158 * the database 159 */ 160 void clearExpiredCookies(long now) { 161 // null mDataBase implies that the host application doesn't support 162 // persistent cookie. 163 if (mDataBase == null) { 164 return; 165 } 166 167 mDataBase.clearExpiredCookies(now); 168 } 169 170 protected void syncFromRamToFlash() { 171 if (DebugFlags.COOKIE_SYNC_MANAGER) { 172 Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash STARTS"); 173 } 174 175 if (!CookieManager.getInstance().acceptCookie()) { 176 return; 177 } 178 179 ArrayList<Cookie> cookieList = CookieManager.getInstance() 180 .getUpdatedCookiesSince(mLastUpdate); 181 mLastUpdate = System.currentTimeMillis(); 182 syncFromRamToFlash(cookieList); 183 184 ArrayList<Cookie> lruList = 185 CookieManager.getInstance().deleteLRUDomain(); 186 syncFromRamToFlash(lruList); 187 188 if (DebugFlags.COOKIE_SYNC_MANAGER) { 189 Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash DONE"); 190 } 191 } 192 193 private void syncFromRamToFlash(ArrayList<Cookie> list) { 194 Iterator<Cookie> iter = list.iterator(); 195 while (iter.hasNext()) { 196 Cookie cookie = iter.next(); 197 if (cookie.mode != Cookie.MODE_NORMAL) { 198 if (cookie.mode != Cookie.MODE_NEW) { 199 mDataBase.deleteCookies(cookie.domain, cookie.path, 200 cookie.name); 201 } 202 if (cookie.mode != Cookie.MODE_DELETED) { 203 mDataBase.addCookie(cookie); 204 CookieManager.getInstance().syncedACookie(cookie); 205 } else { 206 CookieManager.getInstance().deleteACookie(cookie); 207 } 208 } 209 } 210 } 211 212 private static void checkInstanceIsCreated() { 213 if (sRef == null) { 214 throw new IllegalStateException( 215 "CookieSyncManager::createInstance() needs to be called " 216 + "before CookieSyncManager::getInstance()"); 217 } 218 } 219} 220