// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/native/cookie_manager.h"

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_cookie_access_policy.h"
#include "android_webview/browser/net/init_native_callback.h"
#include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
#include "android_webview/native/aw_browser_dependency_factory.h"
#include "base/android/jni_string.h"
#include "base/android/path_utils.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_crypto_delegate.h"
#include "content/public/browser/cookie_store_factory.h"
#include "jni/AwCookieManager_jni.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_options.h"
#include "net/url_request/url_request_context.h"
#include "url/url_constants.h"

using base::FilePath;
using base::WaitableEvent;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertJavaStringToUTF16;
using base::android::ScopedJavaGlobalRef;
using content::BrowserThread;
using net::CookieList;
using net::CookieMonster;

// In the future, we may instead want to inject an explicit CookieStore
// dependency into this object during process initialization to avoid
// depending on the URLRequestContext.
// See issue http://crbug.com/157683

// On the CookieManager methods without a callback and methods with a callback
// when that callback is null can be called from any thread, including threads
// without a message loop. Methods with a non-null callback must be called on
// a thread with a running message loop.

namespace android_webview {

namespace {

typedef base::Callback<void(bool)> BoolCallback;
typedef base::Callback<void(int)> IntCallback;

// Holds a Java BooleanCookieCallback, knows how to invoke it and turn it
// into a base callback.
class BoolCookieCallbackHolder {
 public:
  BoolCookieCallbackHolder(JNIEnv* env, jobject callback) {
    callback_.Reset(env, callback);
  }

  void Invoke(bool result) {
    if (!callback_.is_null()) {
      JNIEnv* env = base::android::AttachCurrentThread();
      Java_AwCookieManager_invokeBooleanCookieCallback(
          env, callback_.obj(), result);
    }
  }

  static BoolCallback ConvertToCallback(
      scoped_ptr<BoolCookieCallbackHolder> me) {
    return base::Bind(&BoolCookieCallbackHolder::Invoke,
                      base::Owned(me.release()));
  }

 private:
  ScopedJavaGlobalRef<jobject> callback_;
  DISALLOW_COPY_AND_ASSIGN(BoolCookieCallbackHolder);
};

// Construct a closure which signals a waitable event if and when the closure
// is called the waitable event must still exist.
static base::Closure SignalEventClosure(WaitableEvent* completion) {
  return base::Bind(&WaitableEvent::Signal, base::Unretained(completion));
}

static void DiscardBool(const base::Closure& f, bool b) {
  f.Run();
}

static BoolCallback BoolCallbackAdapter(const base::Closure& f) {
  return base::Bind(&DiscardBool, f);
}

static void DiscardInt(const base::Closure& f, int i) {
  f.Run();
}

static IntCallback IntCallbackAdapter(const base::Closure& f) {
  return base::Bind(&DiscardInt, f);
}

// Are cookies allowed for file:// URLs by default?
const bool kDefaultFileSchemeAllowed = false;

void ImportLegacyCookieStore(const FilePath& cookie_store_path) {
  // We use the old cookie store to create the new cookie store only if the
  // new cookie store does not exist.
  if (base::PathExists(cookie_store_path))
    return;

  // WebViewClassic gets the database path from Context and appends a
  // hardcoded name. See:
  // https://android.googlesource.com/platform/frameworks/base/+/bf6f6f9d/core/java/android/webkit/JniUtil.java
  // https://android.googlesource.com/platform/external/webkit/+/7151e/
  //     Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
  FilePath old_cookie_store_path;
  base::android::GetDatabaseDirectory(&old_cookie_store_path);
  old_cookie_store_path = old_cookie_store_path.Append(
      FILE_PATH_LITERAL("webviewCookiesChromium.db"));
  if (base::PathExists(old_cookie_store_path) &&
      !base::Move(old_cookie_store_path, cookie_store_path)) {
    LOG(WARNING) << "Failed to move old cookie store path from "
                 << old_cookie_store_path.AsUTF8Unsafe() << " to "
                 << cookie_store_path.AsUTF8Unsafe();
  }
}

void GetUserDataDir(FilePath* user_data_dir) {
  if (!PathService::Get(base::DIR_ANDROID_APP_DATA, user_data_dir)) {
    NOTREACHED() << "Failed to get app data directory for Android WebView";
  }
}

class CookieManager {
 public:
  static CookieManager* GetInstance();

  scoped_refptr<net::CookieStore> GetCookieStore();

  void SetShouldAcceptCookies(bool accept);
  bool GetShouldAcceptCookies();
  void SetCookie(const GURL& host,
                 const std::string& cookie_value,
                 scoped_ptr<BoolCookieCallbackHolder> callback);
  void SetCookieSync(const GURL& host,
                 const std::string& cookie_value);
  std::string GetCookie(const GURL& host);
  void RemoveSessionCookies(scoped_ptr<BoolCookieCallbackHolder> callback);
  void RemoveAllCookies(scoped_ptr<BoolCookieCallbackHolder> callback);
  void RemoveAllCookiesSync();
  void RemoveSessionCookiesSync();
  void RemoveExpiredCookies();
  void FlushCookieStore();
  bool HasCookies();
  bool AllowFileSchemeCookies();
  void SetAcceptFileSchemeCookies(bool accept);

 private:
  friend struct base::DefaultLazyInstanceTraits<CookieManager>;

  CookieManager();
  ~CookieManager();

  void ExecCookieTaskSync(const base::Callback<void(BoolCallback)>& task);
  void ExecCookieTaskSync(const base::Callback<void(IntCallback)>& task);
  void ExecCookieTaskSync(const base::Callback<void(base::Closure)>& task);
  void ExecCookieTask(const base::Closure& task);

  void SetCookieHelper(
      const GURL& host,
      const std::string& value,
      BoolCallback callback);

  void GetCookieValueAsyncHelper(const GURL& host,
                                 std::string* result,
                                 base::Closure complete);
  void GetCookieValueCompleted(base::Closure complete,
                               std::string* result,
                               const std::string& value);

  void RemoveSessionCookiesHelper(BoolCallback callback);
  void RemoveAllCookiesHelper(BoolCallback callback);
  void RemoveCookiesCompleted(BoolCallback callback, int num_deleted);

  void FlushCookieStoreAsyncHelper(base::Closure complete);

  void HasCookiesAsyncHelper(bool* result, base::Closure complete);
  void HasCookiesCompleted(base::Closure complete,
                           bool* result,
                           const CookieList& cookies);

  void CreateCookieMonster(
    const FilePath& user_data_dir,
    const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
  void EnsureCookieMonsterExistsLocked();
  bool AllowFileSchemeCookiesLocked();
  void SetAcceptFileSchemeCookiesLocked(bool accept);

  scoped_refptr<net::CookieMonster> cookie_monster_;
  scoped_refptr<base::MessageLoopProxy> cookie_monster_proxy_;
  base::Lock cookie_monster_lock_;

  scoped_ptr<base::Thread> cookie_monster_client_thread_;
  scoped_ptr<base::Thread> cookie_monster_backend_thread_;

  DISALLOW_COPY_AND_ASSIGN(CookieManager);
};

base::LazyInstance<CookieManager>::Leaky g_lazy_instance;

// static
CookieManager* CookieManager::GetInstance() {
  return g_lazy_instance.Pointer();
}

CookieManager::CookieManager() {
}

CookieManager::~CookieManager() {
}

void CookieManager::CreateCookieMonster(
    const FilePath& user_data_dir,
    const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
  FilePath cookie_store_path =
      user_data_dir.Append(FILE_PATH_LITERAL("Cookies"));

  background_task_runner->PostTask(
      FROM_HERE,
      base::Bind(ImportLegacyCookieStore, cookie_store_path));

  content::CookieStoreConfig cookie_config(
      cookie_store_path,
      content::CookieStoreConfig::RESTORED_SESSION_COOKIES,
      NULL, NULL);
  cookie_config.client_task_runner = client_task_runner;
  cookie_config.background_task_runner = background_task_runner;
  net::CookieStore* cookie_store = content::CreateCookieStore(cookie_config);
  cookie_monster_ = cookie_store->GetCookieMonster();
  SetAcceptFileSchemeCookiesLocked(kDefaultFileSchemeAllowed);
}

void CookieManager::EnsureCookieMonsterExistsLocked() {
  cookie_monster_lock_.AssertAcquired();
  if (cookie_monster_.get()) {
    return;
  }

  // Create cookie monster using WebView-specific threads, as the rest of the
  // browser has not been started yet.
  FilePath user_data_dir;
  GetUserDataDir(&user_data_dir);
  cookie_monster_client_thread_.reset(
      new base::Thread("CookieMonsterClient"));
  cookie_monster_client_thread_->Start();
  cookie_monster_proxy_ = cookie_monster_client_thread_->message_loop_proxy();
  cookie_monster_backend_thread_.reset(
      new base::Thread("CookieMonsterBackend"));
  cookie_monster_backend_thread_->Start();

  CreateCookieMonster(user_data_dir,
                      cookie_monster_proxy_,
                      cookie_monster_backend_thread_->message_loop_proxy());
}

// Executes the |task| on the |cookie_monster_proxy_| message loop and
// waits for it to complete before returning.

// To execute a CookieTask synchronously you must arrange for Signal to be
// called on the waitable event at some point. You can call the bool or int
// versions of ExecCookieTaskSync, these will supply the caller with a dummy
// callback which takes an int/bool, throws it away and calls Signal.
// Alternatively you can call the version which supplies a Closure in which
// case you must call Run on it when you want the unblock the calling code.

// Ignore a bool callback.
void CookieManager::ExecCookieTaskSync(
    const base::Callback<void(BoolCallback)>& task) {
  WaitableEvent completion(false, false);
  ExecCookieTask(
      base::Bind(task, BoolCallbackAdapter(SignalEventClosure(&completion))));
  ScopedAllowWaitForLegacyWebViewApi wait;
  completion.Wait();
}

// Ignore an int callback.
void CookieManager::ExecCookieTaskSync(
    const base::Callback<void(IntCallback)>& task) {
  WaitableEvent completion(false, false);
  ExecCookieTask(
      base::Bind(task, IntCallbackAdapter(SignalEventClosure(&completion))));
  ScopedAllowWaitForLegacyWebViewApi wait;
  completion.Wait();
}

// Call the supplied closure when you want to signal that the blocked code can
// continue.
void CookieManager::ExecCookieTaskSync(
    const base::Callback<void(base::Closure)>& task) {
  WaitableEvent completion(false, false);
  ExecCookieTask(base::Bind(task, SignalEventClosure(&completion)));
  ScopedAllowWaitForLegacyWebViewApi wait;
  completion.Wait();
}

// Executes the |task| on the |cookie_monster_proxy_| message loop.
void CookieManager::ExecCookieTask(const base::Closure& task) {
  base::AutoLock lock(cookie_monster_lock_);
  EnsureCookieMonsterExistsLocked();
  cookie_monster_proxy_->PostTask(FROM_HERE, task);
}

scoped_refptr<net::CookieStore> CookieManager::GetCookieStore() {
  base::AutoLock lock(cookie_monster_lock_);
  EnsureCookieMonsterExistsLocked();
  return cookie_monster_;
}

void CookieManager::SetShouldAcceptCookies(bool accept) {
  AwCookieAccessPolicy::GetInstance()->SetShouldAcceptCookies(accept);
}

bool CookieManager::GetShouldAcceptCookies() {
  return AwCookieAccessPolicy::GetInstance()->GetShouldAcceptCookies();
}

void CookieManager::SetCookie(
    const GURL& host,
    const std::string& cookie_value,
    scoped_ptr<BoolCookieCallbackHolder> callback_holder) {
  BoolCallback callback =
      BoolCookieCallbackHolder::ConvertToCallback(callback_holder.Pass());
  ExecCookieTask(base::Bind(&CookieManager::SetCookieHelper,
                            base::Unretained(this),
                            host,
                            cookie_value,
                            callback));
}

void CookieManager::SetCookieSync(const GURL& host,
                              const std::string& cookie_value) {
  ExecCookieTaskSync(base::Bind(&CookieManager::SetCookieHelper,
                            base::Unretained(this),
                            host,
                            cookie_value));
}

void CookieManager::SetCookieHelper(
    const GURL& host,
    const std::string& value,
    const BoolCallback callback) {
  net::CookieOptions options;
  options.set_include_httponly();

  cookie_monster_->SetCookieWithOptionsAsync(
      host, value, options, callback);
}

std::string CookieManager::GetCookie(const GURL& host) {
  std::string cookie_value;
  ExecCookieTaskSync(base::Bind(&CookieManager::GetCookieValueAsyncHelper,
                            base::Unretained(this),
                            host,
                            &cookie_value));
  return cookie_value;
}

void CookieManager::GetCookieValueAsyncHelper(
    const GURL& host,
    std::string* result,
    base::Closure complete) {
  net::CookieOptions options;
  options.set_include_httponly();

  cookie_monster_->GetCookiesWithOptionsAsync(
      host,
      options,
      base::Bind(&CookieManager::GetCookieValueCompleted,
                 base::Unretained(this),
                 complete,
                 result));
}

void CookieManager::GetCookieValueCompleted(base::Closure complete,
                                            std::string* result,
                                            const std::string& value) {
  *result = value;
  complete.Run();
}

void CookieManager::RemoveSessionCookies(
    scoped_ptr<BoolCookieCallbackHolder> callback_holder) {
  BoolCallback callback =
      BoolCookieCallbackHolder::ConvertToCallback(callback_holder.Pass());
  ExecCookieTask(base::Bind(&CookieManager::RemoveSessionCookiesHelper,
                            base::Unretained(this),
                            callback));
}

void CookieManager::RemoveSessionCookiesSync() {
  ExecCookieTaskSync(base::Bind(&CookieManager::RemoveSessionCookiesHelper,
                            base::Unretained(this)));
}

void CookieManager::RemoveSessionCookiesHelper(
    BoolCallback callback) {
  cookie_monster_->DeleteSessionCookiesAsync(
      base::Bind(&CookieManager::RemoveCookiesCompleted,
                 base::Unretained(this),
                 callback));
}

void CookieManager::RemoveCookiesCompleted(
    BoolCallback callback,
    int num_deleted) {
  callback.Run(num_deleted > 0);
}

void CookieManager::RemoveAllCookies(
    scoped_ptr<BoolCookieCallbackHolder> callback_holder) {
  BoolCallback callback =
      BoolCookieCallbackHolder::ConvertToCallback(callback_holder.Pass());
  ExecCookieTask(base::Bind(&CookieManager::RemoveAllCookiesHelper,
                            base::Unretained(this),
                            callback));
}

void CookieManager::RemoveAllCookiesSync() {
  ExecCookieTaskSync(base::Bind(&CookieManager::RemoveAllCookiesHelper,
                            base::Unretained(this)));
}

void CookieManager::RemoveAllCookiesHelper(
    const BoolCallback callback) {
  cookie_monster_->DeleteAllAsync(
      base::Bind(&CookieManager::RemoveCookiesCompleted,
                 base::Unretained(this),
                 callback));
}

void CookieManager::RemoveExpiredCookies() {
  // HasCookies will call GetAllCookiesAsync, which in turn will force a GC.
  HasCookies();
}

void CookieManager::FlushCookieStore() {
  ExecCookieTaskSync(base::Bind(&CookieManager::FlushCookieStoreAsyncHelper,
                            base::Unretained(this)));
}

void CookieManager::FlushCookieStoreAsyncHelper(
    base::Closure complete) {
  cookie_monster_->FlushStore(complete);
}

bool CookieManager::HasCookies() {
  bool has_cookies;
  ExecCookieTaskSync(base::Bind(&CookieManager::HasCookiesAsyncHelper,
                            base::Unretained(this),
                            &has_cookies));
  return has_cookies;
}

// TODO(kristianm): Simplify this, copying the entire list around
// should not be needed.
void CookieManager::HasCookiesAsyncHelper(bool* result,
                                          base::Closure complete) {
  cookie_monster_->GetAllCookiesAsync(
      base::Bind(&CookieManager::HasCookiesCompleted,
                 base::Unretained(this),
                 complete,
                 result));
}

void CookieManager::HasCookiesCompleted(base::Closure complete,
                                        bool* result,
                                        const CookieList& cookies) {
  *result = cookies.size() != 0;
  complete.Run();
}

bool CookieManager::AllowFileSchemeCookies() {
  base::AutoLock lock(cookie_monster_lock_);
  EnsureCookieMonsterExistsLocked();
  return AllowFileSchemeCookiesLocked();
}

bool CookieManager::AllowFileSchemeCookiesLocked() {
  return cookie_monster_->IsCookieableScheme(url::kFileScheme);
}

void CookieManager::SetAcceptFileSchemeCookies(bool accept) {
  base::AutoLock lock(cookie_monster_lock_);
  EnsureCookieMonsterExistsLocked();
  SetAcceptFileSchemeCookiesLocked(accept);
}

void CookieManager::SetAcceptFileSchemeCookiesLocked(bool accept) {
  // The docs on CookieManager base class state the API must not be called after
  // creating a CookieManager instance (which contradicts its own internal
  // implementation) but this code does rely on the essence of that comment, as
  // the monster will DCHECK here if it has already been lazy initialized (i.e.
  // if cookies have been read or written from the store). If that turns out to
  // be a problemin future, it looks like it maybe possible to relax the DCHECK.
  cookie_monster_->SetEnableFileScheme(accept);
}

}  // namespace

static void SetShouldAcceptCookies(JNIEnv* env, jobject obj, jboolean accept) {
  CookieManager::GetInstance()->SetShouldAcceptCookies(accept);
}

static jboolean GetShouldAcceptCookies(JNIEnv* env, jobject obj) {
  return CookieManager::GetInstance()->GetShouldAcceptCookies();
}

static void SetCookie(JNIEnv* env,
                      jobject obj,
                      jstring url,
                      jstring value,
                      jobject java_callback) {
  GURL host(ConvertJavaStringToUTF16(env, url));
  std::string cookie_value(ConvertJavaStringToUTF8(env, value));
  scoped_ptr<BoolCookieCallbackHolder> callback(
      new BoolCookieCallbackHolder(env, java_callback));
  CookieManager::GetInstance()->SetCookie(host, cookie_value, callback.Pass());
}

static void SetCookieSync(JNIEnv* env,
                      jobject obj,
                      jstring url,
                      jstring value) {
  GURL host(ConvertJavaStringToUTF16(env, url));
  std::string cookie_value(ConvertJavaStringToUTF8(env, value));

  CookieManager::GetInstance()->SetCookieSync(host, cookie_value);
}

static jstring GetCookie(JNIEnv* env, jobject obj, jstring url) {
  GURL host(ConvertJavaStringToUTF16(env, url));

  return base::android::ConvertUTF8ToJavaString(
      env,
      CookieManager::GetInstance()->GetCookie(host)).Release();
}

static void RemoveSessionCookies(JNIEnv* env,
                                jobject obj,
                                jobject java_callback) {
  scoped_ptr<BoolCookieCallbackHolder> callback(
      new BoolCookieCallbackHolder(env, java_callback));
  CookieManager::GetInstance()->RemoveSessionCookies(callback.Pass());
}

static void RemoveSessionCookiesSync(JNIEnv* env, jobject obj) {
    CookieManager::GetInstance()->RemoveSessionCookiesSync();
}

static void RemoveAllCookies(JNIEnv* env, jobject obj, jobject java_callback) {
  scoped_ptr<BoolCookieCallbackHolder> callback(
      new BoolCookieCallbackHolder(env, java_callback));
  CookieManager::GetInstance()->RemoveAllCookies(callback.Pass());
}

static void RemoveAllCookiesSync(JNIEnv* env, jobject obj) {
  CookieManager::GetInstance()->RemoveAllCookiesSync();
}

static void RemoveExpiredCookies(JNIEnv* env, jobject obj) {
  CookieManager::GetInstance()->RemoveExpiredCookies();
}

static void FlushCookieStore(JNIEnv* env, jobject obj) {
  CookieManager::GetInstance()->FlushCookieStore();
}

static jboolean HasCookies(JNIEnv* env, jobject obj) {
  return CookieManager::GetInstance()->HasCookies();
}

static jboolean AllowFileSchemeCookies(JNIEnv* env, jobject obj) {
  return CookieManager::GetInstance()->AllowFileSchemeCookies();
}

static void SetAcceptFileSchemeCookies(JNIEnv* env, jobject obj,
                                       jboolean accept) {
  return CookieManager::GetInstance()->SetAcceptFileSchemeCookies(accept);
}

scoped_refptr<net::CookieStore> CreateCookieStore(
    AwBrowserContext* browser_context) {
  return CookieManager::GetInstance()->GetCookieStore();
}

bool RegisterCookieManager(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

}  // android_webview namespace
