Home | History | Annotate | Download | only in native
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "android_webview/native/cookie_manager.h"
      6 
      7 #include "android_webview/browser/aw_browser_context.h"
      8 #include "android_webview/browser/aw_cookie_access_policy.h"
      9 #include "android_webview/browser/net/init_native_callback.h"
     10 #include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
     11 #include "android_webview/native/aw_browser_dependency_factory.h"
     12 #include "base/android/jni_string.h"
     13 #include "base/android/path_utils.h"
     14 #include "base/bind.h"
     15 #include "base/bind_helpers.h"
     16 #include "base/files/file_path.h"
     17 #include "base/files/file_util.h"
     18 #include "base/lazy_instance.h"
     19 #include "base/message_loop/message_loop.h"
     20 #include "base/message_loop/message_loop_proxy.h"
     21 #include "base/path_service.h"
     22 #include "base/synchronization/lock.h"
     23 #include "base/synchronization/waitable_event.h"
     24 #include "base/threading/sequenced_worker_pool.h"
     25 #include "base/threading/thread.h"
     26 #include "base/threading/thread_restrictions.h"
     27 #include "content/public/browser/browser_context.h"
     28 #include "content/public/browser/browser_thread.h"
     29 #include "content/public/browser/cookie_crypto_delegate.h"
     30 #include "content/public/browser/cookie_store_factory.h"
     31 #include "jni/AwCookieManager_jni.h"
     32 #include "net/cookies/cookie_monster.h"
     33 #include "net/cookies/cookie_options.h"
     34 #include "net/url_request/url_request_context.h"
     35 #include "url/url_constants.h"
     36 
     37 using base::FilePath;
     38 using base::WaitableEvent;
     39 using base::android::ConvertJavaStringToUTF8;
     40 using base::android::ConvertJavaStringToUTF16;
     41 using base::android::ScopedJavaGlobalRef;
     42 using content::BrowserThread;
     43 using net::CookieList;
     44 using net::CookieMonster;
     45 
     46 // In the future, we may instead want to inject an explicit CookieStore
     47 // dependency into this object during process initialization to avoid
     48 // depending on the URLRequestContext.
     49 // See issue http://crbug.com/157683
     50 
     51 // On the CookieManager methods without a callback and methods with a callback
     52 // when that callback is null can be called from any thread, including threads
     53 // without a message loop. Methods with a non-null callback must be called on
     54 // a thread with a running message loop.
     55 
     56 namespace android_webview {
     57 
     58 namespace {
     59 
     60 typedef base::Callback<void(bool)> BoolCallback;
     61 typedef base::Callback<void(int)> IntCallback;
     62 
     63 // Holds a Java BooleanCookieCallback, knows how to invoke it and turn it
     64 // into a base callback.
     65 class BoolCookieCallbackHolder {
     66  public:
     67   BoolCookieCallbackHolder(JNIEnv* env, jobject callback) {
     68     callback_.Reset(env, callback);
     69   }
     70 
     71   void Invoke(bool result) {
     72     if (!callback_.is_null()) {
     73       JNIEnv* env = base::android::AttachCurrentThread();
     74       Java_AwCookieManager_invokeBooleanCookieCallback(
     75           env, callback_.obj(), result);
     76     }
     77   }
     78 
     79   static BoolCallback ConvertToCallback(
     80       scoped_ptr<BoolCookieCallbackHolder> me) {
     81     return base::Bind(&BoolCookieCallbackHolder::Invoke,
     82                       base::Owned(me.release()));
     83   }
     84 
     85  private:
     86   ScopedJavaGlobalRef<jobject> callback_;
     87   DISALLOW_COPY_AND_ASSIGN(BoolCookieCallbackHolder);
     88 };
     89 
     90 // Construct a closure which signals a waitable event if and when the closure
     91 // is called the waitable event must still exist.
     92 static base::Closure SignalEventClosure(WaitableEvent* completion) {
     93   return base::Bind(&WaitableEvent::Signal, base::Unretained(completion));
     94 }
     95 
     96 static void DiscardBool(const base::Closure& f, bool b) {
     97   f.Run();
     98 }
     99 
    100 static BoolCallback BoolCallbackAdapter(const base::Closure& f) {
    101   return base::Bind(&DiscardBool, f);
    102 }
    103 
    104 static void DiscardInt(const base::Closure& f, int i) {
    105   f.Run();
    106 }
    107 
    108 static IntCallback IntCallbackAdapter(const base::Closure& f) {
    109   return base::Bind(&DiscardInt, f);
    110 }
    111 
    112 // Are cookies allowed for file:// URLs by default?
    113 const bool kDefaultFileSchemeAllowed = false;
    114 
    115 void ImportLegacyCookieStore(const FilePath& cookie_store_path) {
    116   // We use the old cookie store to create the new cookie store only if the
    117   // new cookie store does not exist.
    118   if (base::PathExists(cookie_store_path))
    119     return;
    120 
    121   // WebViewClassic gets the database path from Context and appends a
    122   // hardcoded name. See:
    123   // https://android.googlesource.com/platform/frameworks/base/+/bf6f6f9d/core/java/android/webkit/JniUtil.java
    124   // https://android.googlesource.com/platform/external/webkit/+/7151e/
    125   //     Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
    126   FilePath old_cookie_store_path;
    127   base::android::GetDatabaseDirectory(&old_cookie_store_path);
    128   old_cookie_store_path = old_cookie_store_path.Append(
    129       FILE_PATH_LITERAL("webviewCookiesChromium.db"));
    130   if (base::PathExists(old_cookie_store_path) &&
    131       !base::Move(old_cookie_store_path, cookie_store_path)) {
    132     LOG(WARNING) << "Failed to move old cookie store path from "
    133                  << old_cookie_store_path.AsUTF8Unsafe() << " to "
    134                  << cookie_store_path.AsUTF8Unsafe();
    135   }
    136 }
    137 
    138 void GetUserDataDir(FilePath* user_data_dir) {
    139   if (!PathService::Get(base::DIR_ANDROID_APP_DATA, user_data_dir)) {
    140     NOTREACHED() << "Failed to get app data directory for Android WebView";
    141   }
    142 }
    143 
    144 class CookieManager {
    145  public:
    146   static CookieManager* GetInstance();
    147 
    148   scoped_refptr<net::CookieStore> GetCookieStore();
    149 
    150   void SetShouldAcceptCookies(bool accept);
    151   bool GetShouldAcceptCookies();
    152   void SetCookie(const GURL& host,
    153                  const std::string& cookie_value,
    154                  scoped_ptr<BoolCookieCallbackHolder> callback);
    155   void SetCookieSync(const GURL& host,
    156                  const std::string& cookie_value);
    157   std::string GetCookie(const GURL& host);
    158   void RemoveSessionCookies(scoped_ptr<BoolCookieCallbackHolder> callback);
    159   void RemoveAllCookies(scoped_ptr<BoolCookieCallbackHolder> callback);
    160   void RemoveAllCookiesSync();
    161   void RemoveSessionCookiesSync();
    162   void RemoveExpiredCookies();
    163   void FlushCookieStore();
    164   bool HasCookies();
    165   bool AllowFileSchemeCookies();
    166   void SetAcceptFileSchemeCookies(bool accept);
    167 
    168  private:
    169   friend struct base::DefaultLazyInstanceTraits<CookieManager>;
    170 
    171   CookieManager();
    172   ~CookieManager();
    173 
    174   void ExecCookieTaskSync(const base::Callback<void(BoolCallback)>& task);
    175   void ExecCookieTaskSync(const base::Callback<void(IntCallback)>& task);
    176   void ExecCookieTaskSync(const base::Callback<void(base::Closure)>& task);
    177   void ExecCookieTask(const base::Closure& task);
    178 
    179   void SetCookieHelper(
    180       const GURL& host,
    181       const std::string& value,
    182       BoolCallback callback);
    183 
    184   void GetCookieValueAsyncHelper(const GURL& host,
    185                                  std::string* result,
    186                                  base::Closure complete);
    187   void GetCookieValueCompleted(base::Closure complete,
    188                                std::string* result,
    189                                const std::string& value);
    190 
    191   void RemoveSessionCookiesHelper(BoolCallback callback);
    192   void RemoveAllCookiesHelper(BoolCallback callback);
    193   void RemoveCookiesCompleted(BoolCallback callback, int num_deleted);
    194 
    195   void FlushCookieStoreAsyncHelper(base::Closure complete);
    196 
    197   void HasCookiesAsyncHelper(bool* result, base::Closure complete);
    198   void HasCookiesCompleted(base::Closure complete,
    199                            bool* result,
    200                            const CookieList& cookies);
    201 
    202   void CreateCookieMonster(
    203     const FilePath& user_data_dir,
    204     const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
    205     const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
    206   void EnsureCookieMonsterExistsLocked();
    207   bool AllowFileSchemeCookiesLocked();
    208   void SetAcceptFileSchemeCookiesLocked(bool accept);
    209 
    210   scoped_refptr<net::CookieMonster> cookie_monster_;
    211   scoped_refptr<base::MessageLoopProxy> cookie_monster_proxy_;
    212   base::Lock cookie_monster_lock_;
    213 
    214   scoped_ptr<base::Thread> cookie_monster_client_thread_;
    215   scoped_ptr<base::Thread> cookie_monster_backend_thread_;
    216 
    217   DISALLOW_COPY_AND_ASSIGN(CookieManager);
    218 };
    219 
    220 base::LazyInstance<CookieManager>::Leaky g_lazy_instance;
    221 
    222 // static
    223 CookieManager* CookieManager::GetInstance() {
    224   return g_lazy_instance.Pointer();
    225 }
    226 
    227 CookieManager::CookieManager() {
    228 }
    229 
    230 CookieManager::~CookieManager() {
    231 }
    232 
    233 void CookieManager::CreateCookieMonster(
    234     const FilePath& user_data_dir,
    235     const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
    236     const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
    237   FilePath cookie_store_path =
    238       user_data_dir.Append(FILE_PATH_LITERAL("Cookies"));
    239 
    240   background_task_runner->PostTask(
    241       FROM_HERE,
    242       base::Bind(ImportLegacyCookieStore, cookie_store_path));
    243 
    244   content::CookieStoreConfig cookie_config(
    245       cookie_store_path,
    246       content::CookieStoreConfig::RESTORED_SESSION_COOKIES,
    247       NULL, NULL);
    248   cookie_config.client_task_runner = client_task_runner;
    249   cookie_config.background_task_runner = background_task_runner;
    250   net::CookieStore* cookie_store = content::CreateCookieStore(cookie_config);
    251   cookie_monster_ = cookie_store->GetCookieMonster();
    252   SetAcceptFileSchemeCookiesLocked(kDefaultFileSchemeAllowed);
    253 }
    254 
    255 void CookieManager::EnsureCookieMonsterExistsLocked() {
    256   cookie_monster_lock_.AssertAcquired();
    257   if (cookie_monster_.get()) {
    258     return;
    259   }
    260 
    261   // Create cookie monster using WebView-specific threads, as the rest of the
    262   // browser has not been started yet.
    263   FilePath user_data_dir;
    264   GetUserDataDir(&user_data_dir);
    265   cookie_monster_client_thread_.reset(
    266       new base::Thread("CookieMonsterClient"));
    267   cookie_monster_client_thread_->Start();
    268   cookie_monster_proxy_ = cookie_monster_client_thread_->message_loop_proxy();
    269   cookie_monster_backend_thread_.reset(
    270       new base::Thread("CookieMonsterBackend"));
    271   cookie_monster_backend_thread_->Start();
    272 
    273   CreateCookieMonster(user_data_dir,
    274                       cookie_monster_proxy_,
    275                       cookie_monster_backend_thread_->message_loop_proxy());
    276 }
    277 
    278 // Executes the |task| on the |cookie_monster_proxy_| message loop and
    279 // waits for it to complete before returning.
    280 
    281 // To execute a CookieTask synchronously you must arrange for Signal to be
    282 // called on the waitable event at some point. You can call the bool or int
    283 // versions of ExecCookieTaskSync, these will supply the caller with a dummy
    284 // callback which takes an int/bool, throws it away and calls Signal.
    285 // Alternatively you can call the version which supplies a Closure in which
    286 // case you must call Run on it when you want the unblock the calling code.
    287 
    288 // Ignore a bool callback.
    289 void CookieManager::ExecCookieTaskSync(
    290     const base::Callback<void(BoolCallback)>& task) {
    291   WaitableEvent completion(false, false);
    292   ExecCookieTask(
    293       base::Bind(task, BoolCallbackAdapter(SignalEventClosure(&completion))));
    294   ScopedAllowWaitForLegacyWebViewApi wait;
    295   completion.Wait();
    296 }
    297 
    298 // Ignore an int callback.
    299 void CookieManager::ExecCookieTaskSync(
    300     const base::Callback<void(IntCallback)>& task) {
    301   WaitableEvent completion(false, false);
    302   ExecCookieTask(
    303       base::Bind(task, IntCallbackAdapter(SignalEventClosure(&completion))));
    304   ScopedAllowWaitForLegacyWebViewApi wait;
    305   completion.Wait();
    306 }
    307 
    308 // Call the supplied closure when you want to signal that the blocked code can
    309 // continue.
    310 void CookieManager::ExecCookieTaskSync(
    311     const base::Callback<void(base::Closure)>& task) {
    312   WaitableEvent completion(false, false);
    313   ExecCookieTask(base::Bind(task, SignalEventClosure(&completion)));
    314   ScopedAllowWaitForLegacyWebViewApi wait;
    315   completion.Wait();
    316 }
    317 
    318 // Executes the |task| on the |cookie_monster_proxy_| message loop.
    319 void CookieManager::ExecCookieTask(const base::Closure& task) {
    320   base::AutoLock lock(cookie_monster_lock_);
    321   EnsureCookieMonsterExistsLocked();
    322   cookie_monster_proxy_->PostTask(FROM_HERE, task);
    323 }
    324 
    325 scoped_refptr<net::CookieStore> CookieManager::GetCookieStore() {
    326   base::AutoLock lock(cookie_monster_lock_);
    327   EnsureCookieMonsterExistsLocked();
    328   return cookie_monster_;
    329 }
    330 
    331 void CookieManager::SetShouldAcceptCookies(bool accept) {
    332   AwCookieAccessPolicy::GetInstance()->SetShouldAcceptCookies(accept);
    333 }
    334 
    335 bool CookieManager::GetShouldAcceptCookies() {
    336   return AwCookieAccessPolicy::GetInstance()->GetShouldAcceptCookies();
    337 }
    338 
    339 void CookieManager::SetCookie(
    340     const GURL& host,
    341     const std::string& cookie_value,
    342     scoped_ptr<BoolCookieCallbackHolder> callback_holder) {
    343   BoolCallback callback =
    344       BoolCookieCallbackHolder::ConvertToCallback(callback_holder.Pass());
    345   ExecCookieTask(base::Bind(&CookieManager::SetCookieHelper,
    346                             base::Unretained(this),
    347                             host,
    348                             cookie_value,
    349                             callback));
    350 }
    351 
    352 void CookieManager::SetCookieSync(const GURL& host,
    353                               const std::string& cookie_value) {
    354   ExecCookieTaskSync(base::Bind(&CookieManager::SetCookieHelper,
    355                             base::Unretained(this),
    356                             host,
    357                             cookie_value));
    358 }
    359 
    360 void CookieManager::SetCookieHelper(
    361     const GURL& host,
    362     const std::string& value,
    363     const BoolCallback callback) {
    364   net::CookieOptions options;
    365   options.set_include_httponly();
    366 
    367   cookie_monster_->SetCookieWithOptionsAsync(
    368       host, value, options, callback);
    369 }
    370 
    371 std::string CookieManager::GetCookie(const GURL& host) {
    372   std::string cookie_value;
    373   ExecCookieTaskSync(base::Bind(&CookieManager::GetCookieValueAsyncHelper,
    374                             base::Unretained(this),
    375                             host,
    376                             &cookie_value));
    377   return cookie_value;
    378 }
    379 
    380 void CookieManager::GetCookieValueAsyncHelper(
    381     const GURL& host,
    382     std::string* result,
    383     base::Closure complete) {
    384   net::CookieOptions options;
    385   options.set_include_httponly();
    386 
    387   cookie_monster_->GetCookiesWithOptionsAsync(
    388       host,
    389       options,
    390       base::Bind(&CookieManager::GetCookieValueCompleted,
    391                  base::Unretained(this),
    392                  complete,
    393                  result));
    394 }
    395 
    396 void CookieManager::GetCookieValueCompleted(base::Closure complete,
    397                                             std::string* result,
    398                                             const std::string& value) {
    399   *result = value;
    400   complete.Run();
    401 }
    402 
    403 void CookieManager::RemoveSessionCookies(
    404     scoped_ptr<BoolCookieCallbackHolder> callback_holder) {
    405   BoolCallback callback =
    406       BoolCookieCallbackHolder::ConvertToCallback(callback_holder.Pass());
    407   ExecCookieTask(base::Bind(&CookieManager::RemoveSessionCookiesHelper,
    408                             base::Unretained(this),
    409                             callback));
    410 }
    411 
    412 void CookieManager::RemoveSessionCookiesSync() {
    413   ExecCookieTaskSync(base::Bind(&CookieManager::RemoveSessionCookiesHelper,
    414                             base::Unretained(this)));
    415 }
    416 
    417 void CookieManager::RemoveSessionCookiesHelper(
    418     BoolCallback callback) {
    419   cookie_monster_->DeleteSessionCookiesAsync(
    420       base::Bind(&CookieManager::RemoveCookiesCompleted,
    421                  base::Unretained(this),
    422                  callback));
    423 }
    424 
    425 void CookieManager::RemoveCookiesCompleted(
    426     BoolCallback callback,
    427     int num_deleted) {
    428   callback.Run(num_deleted > 0);
    429 }
    430 
    431 void CookieManager::RemoveAllCookies(
    432     scoped_ptr<BoolCookieCallbackHolder> callback_holder) {
    433   BoolCallback callback =
    434       BoolCookieCallbackHolder::ConvertToCallback(callback_holder.Pass());
    435   ExecCookieTask(base::Bind(&CookieManager::RemoveAllCookiesHelper,
    436                             base::Unretained(this),
    437                             callback));
    438 }
    439 
    440 void CookieManager::RemoveAllCookiesSync() {
    441   ExecCookieTaskSync(base::Bind(&CookieManager::RemoveAllCookiesHelper,
    442                             base::Unretained(this)));
    443 }
    444 
    445 void CookieManager::RemoveAllCookiesHelper(
    446     const BoolCallback callback) {
    447   cookie_monster_->DeleteAllAsync(
    448       base::Bind(&CookieManager::RemoveCookiesCompleted,
    449                  base::Unretained(this),
    450                  callback));
    451 }
    452 
    453 void CookieManager::RemoveExpiredCookies() {
    454   // HasCookies will call GetAllCookiesAsync, which in turn will force a GC.
    455   HasCookies();
    456 }
    457 
    458 void CookieManager::FlushCookieStore() {
    459   ExecCookieTaskSync(base::Bind(&CookieManager::FlushCookieStoreAsyncHelper,
    460                             base::Unretained(this)));
    461 }
    462 
    463 void CookieManager::FlushCookieStoreAsyncHelper(
    464     base::Closure complete) {
    465   cookie_monster_->FlushStore(complete);
    466 }
    467 
    468 bool CookieManager::HasCookies() {
    469   bool has_cookies;
    470   ExecCookieTaskSync(base::Bind(&CookieManager::HasCookiesAsyncHelper,
    471                             base::Unretained(this),
    472                             &has_cookies));
    473   return has_cookies;
    474 }
    475 
    476 // TODO(kristianm): Simplify this, copying the entire list around
    477 // should not be needed.
    478 void CookieManager::HasCookiesAsyncHelper(bool* result,
    479                                           base::Closure complete) {
    480   cookie_monster_->GetAllCookiesAsync(
    481       base::Bind(&CookieManager::HasCookiesCompleted,
    482                  base::Unretained(this),
    483                  complete,
    484                  result));
    485 }
    486 
    487 void CookieManager::HasCookiesCompleted(base::Closure complete,
    488                                         bool* result,
    489                                         const CookieList& cookies) {
    490   *result = cookies.size() != 0;
    491   complete.Run();
    492 }
    493 
    494 bool CookieManager::AllowFileSchemeCookies() {
    495   base::AutoLock lock(cookie_monster_lock_);
    496   EnsureCookieMonsterExistsLocked();
    497   return AllowFileSchemeCookiesLocked();
    498 }
    499 
    500 bool CookieManager::AllowFileSchemeCookiesLocked() {
    501   return cookie_monster_->IsCookieableScheme(url::kFileScheme);
    502 }
    503 
    504 void CookieManager::SetAcceptFileSchemeCookies(bool accept) {
    505   base::AutoLock lock(cookie_monster_lock_);
    506   EnsureCookieMonsterExistsLocked();
    507   SetAcceptFileSchemeCookiesLocked(accept);
    508 }
    509 
    510 void CookieManager::SetAcceptFileSchemeCookiesLocked(bool accept) {
    511   // The docs on CookieManager base class state the API must not be called after
    512   // creating a CookieManager instance (which contradicts its own internal
    513   // implementation) but this code does rely on the essence of that comment, as
    514   // the monster will DCHECK here if it has already been lazy initialized (i.e.
    515   // if cookies have been read or written from the store). If that turns out to
    516   // be a problemin future, it looks like it maybe possible to relax the DCHECK.
    517   cookie_monster_->SetEnableFileScheme(accept);
    518 }
    519 
    520 }  // namespace
    521 
    522 static void SetShouldAcceptCookies(JNIEnv* env, jobject obj, jboolean accept) {
    523   CookieManager::GetInstance()->SetShouldAcceptCookies(accept);
    524 }
    525 
    526 static jboolean GetShouldAcceptCookies(JNIEnv* env, jobject obj) {
    527   return CookieManager::GetInstance()->GetShouldAcceptCookies();
    528 }
    529 
    530 static void SetCookie(JNIEnv* env,
    531                       jobject obj,
    532                       jstring url,
    533                       jstring value,
    534                       jobject java_callback) {
    535   GURL host(ConvertJavaStringToUTF16(env, url));
    536   std::string cookie_value(ConvertJavaStringToUTF8(env, value));
    537   scoped_ptr<BoolCookieCallbackHolder> callback(
    538       new BoolCookieCallbackHolder(env, java_callback));
    539   CookieManager::GetInstance()->SetCookie(host, cookie_value, callback.Pass());
    540 }
    541 
    542 static void SetCookieSync(JNIEnv* env,
    543                       jobject obj,
    544                       jstring url,
    545                       jstring value) {
    546   GURL host(ConvertJavaStringToUTF16(env, url));
    547   std::string cookie_value(ConvertJavaStringToUTF8(env, value));
    548 
    549   CookieManager::GetInstance()->SetCookieSync(host, cookie_value);
    550 }
    551 
    552 static jstring GetCookie(JNIEnv* env, jobject obj, jstring url) {
    553   GURL host(ConvertJavaStringToUTF16(env, url));
    554 
    555   return base::android::ConvertUTF8ToJavaString(
    556       env,
    557       CookieManager::GetInstance()->GetCookie(host)).Release();
    558 }
    559 
    560 static void RemoveSessionCookies(JNIEnv* env,
    561                                 jobject obj,
    562                                 jobject java_callback) {
    563   scoped_ptr<BoolCookieCallbackHolder> callback(
    564       new BoolCookieCallbackHolder(env, java_callback));
    565   CookieManager::GetInstance()->RemoveSessionCookies(callback.Pass());
    566 }
    567 
    568 static void RemoveSessionCookiesSync(JNIEnv* env, jobject obj) {
    569     CookieManager::GetInstance()->RemoveSessionCookiesSync();
    570 }
    571 
    572 static void RemoveAllCookies(JNIEnv* env, jobject obj, jobject java_callback) {
    573   scoped_ptr<BoolCookieCallbackHolder> callback(
    574       new BoolCookieCallbackHolder(env, java_callback));
    575   CookieManager::GetInstance()->RemoveAllCookies(callback.Pass());
    576 }
    577 
    578 static void RemoveAllCookiesSync(JNIEnv* env, jobject obj) {
    579   CookieManager::GetInstance()->RemoveAllCookiesSync();
    580 }
    581 
    582 static void RemoveExpiredCookies(JNIEnv* env, jobject obj) {
    583   CookieManager::GetInstance()->RemoveExpiredCookies();
    584 }
    585 
    586 static void FlushCookieStore(JNIEnv* env, jobject obj) {
    587   CookieManager::GetInstance()->FlushCookieStore();
    588 }
    589 
    590 static jboolean HasCookies(JNIEnv* env, jobject obj) {
    591   return CookieManager::GetInstance()->HasCookies();
    592 }
    593 
    594 static jboolean AllowFileSchemeCookies(JNIEnv* env, jobject obj) {
    595   return CookieManager::GetInstance()->AllowFileSchemeCookies();
    596 }
    597 
    598 static void SetAcceptFileSchemeCookies(JNIEnv* env, jobject obj,
    599                                        jboolean accept) {
    600   return CookieManager::GetInstance()->SetAcceptFileSchemeCookies(accept);
    601 }
    602 
    603 scoped_refptr<net::CookieStore> CreateCookieStore(
    604     AwBrowserContext* browser_context) {
    605   return CookieManager::GetInstance()->GetCookieStore();
    606 }
    607 
    608 bool RegisterCookieManager(JNIEnv* env) {
    609   return RegisterNativesImpl(env);
    610 }
    611 
    612 }  // android_webview namespace
    613