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