// Copyright (c) 2013 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/aw_quota_manager_bridge_impl.h"

#include <set>

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_content_browser_client.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/synchronization/waitable_event.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_client.h"
#include "jni/AwQuotaManagerBridge_jni.h"
#include "url/gurl.h"
#include "webkit/browser/quota/quota_manager.h"
#include "webkit/common/quota/quota_types.h"

using base::android::AttachCurrentThread;
using content::BrowserThread;
using content::StoragePartition;
using quota::QuotaClient;
using quota::QuotaManager;

namespace android_webview {

namespace {

// This object lives on UI and IO threads. Care need to be taken to make sure
// there are no concurrent accesses to instance variables. Also this object
// is refcounted in the various callbacks, and is destroyed when all callbacks
// are destroyed at the end of DoneOnUIThread.
class GetOriginsTask : public base::RefCountedThreadSafe<GetOriginsTask> {
 public:
  GetOriginsTask(
      const AwQuotaManagerBridgeImpl::GetOriginsCallback& callback,
      QuotaManager* quota_manager);

  void Run();

 private:
  friend class base::RefCountedThreadSafe<GetOriginsTask>;
  ~GetOriginsTask();

  void OnOriginsObtained(const std::set<GURL>& origins,
                         quota::StorageType type);

  void OnUsageAndQuotaObtained(const GURL& origin,
                               quota::QuotaStatusCode status_code,
                               int64 usage,
                               int64 quota);

  void CheckDone();
  void DoneOnUIThread();

  AwQuotaManagerBridgeImpl::GetOriginsCallback ui_callback_;
  scoped_refptr<QuotaManager> quota_manager_;

  std::vector<std::string> origin_;
  std::vector<int64> usage_;
  std::vector<int64> quota_;

  size_t num_callbacks_to_wait_;
  size_t num_callbacks_received_;

  DISALLOW_COPY_AND_ASSIGN(GetOriginsTask);
};

GetOriginsTask::GetOriginsTask(
    const AwQuotaManagerBridgeImpl::GetOriginsCallback& callback,
    QuotaManager* quota_manager)
    : ui_callback_(callback),
      quota_manager_(quota_manager) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

GetOriginsTask::~GetOriginsTask() {}

void GetOriginsTask::Run() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  BrowserThread::PostTask(
      BrowserThread::IO,
      FROM_HERE,
      base::Bind(&QuotaManager::GetOriginsModifiedSince,
                 quota_manager_,
                 quota::kStorageTypeTemporary,
                 base::Time()  /* Since beginning of time. */,
                 base::Bind(&GetOriginsTask::OnOriginsObtained, this)));
}

void GetOriginsTask::OnOriginsObtained(
    const std::set<GURL>& origins, quota::StorageType type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  num_callbacks_to_wait_ = origins.size();
  num_callbacks_received_ = 0u;

  for (std::set<GURL>::const_iterator origin = origins.begin();
       origin != origins.end();
       ++origin) {
    quota_manager_->GetUsageAndQuota(
        *origin,
        type,
        base::Bind(&GetOriginsTask::OnUsageAndQuotaObtained, this, *origin));
  }

  CheckDone();
}

void GetOriginsTask::OnUsageAndQuotaObtained(const GURL& origin,
                                             quota::QuotaStatusCode status_code,
                                             int64 usage,
                                             int64 quota) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (status_code == quota::kQuotaStatusOk) {
    origin_.push_back(origin.spec());
    usage_.push_back(usage);
    quota_.push_back(quota);
  }

  ++num_callbacks_received_;
  CheckDone();
}

void GetOriginsTask::CheckDone() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (num_callbacks_received_ == num_callbacks_to_wait_) {
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        base::Bind(&GetOriginsTask::DoneOnUIThread, this));
  } else if (num_callbacks_received_ > num_callbacks_to_wait_) {
    NOTREACHED();
  }
}

// This method is to avoid copying the 3 vector arguments into a bound callback.
void GetOriginsTask::DoneOnUIThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  ui_callback_.Run(origin_, usage_, quota_);
}

void RunOnUIThread(const base::Closure& task) {
  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    task.Run();
  } else {
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task);
  }
}

}  // namespace


// static
jint GetDefaultNativeAwQuotaManagerBridge(JNIEnv* env, jclass clazz) {
  AwBrowserContext* browser_context =
      AwContentBrowserClient::GetAwBrowserContext();

  AwQuotaManagerBridgeImpl* bridge = static_cast<AwQuotaManagerBridgeImpl*>(
      browser_context->GetQuotaManagerBridge());
  DCHECK(bridge);
  return reinterpret_cast<jint>(bridge);
}

// static
scoped_refptr<AwQuotaManagerBridge> AwQuotaManagerBridgeImpl::Create(
    AwBrowserContext* browser_context) {
  return new AwQuotaManagerBridgeImpl(browser_context);
}

AwQuotaManagerBridgeImpl::AwQuotaManagerBridgeImpl(
    AwBrowserContext* browser_context)
    : weak_factory_(this),
      browser_context_(browser_context) {
}

AwQuotaManagerBridgeImpl::~AwQuotaManagerBridgeImpl() {}

void AwQuotaManagerBridgeImpl::Init(JNIEnv* env, jobject object) {
  java_ref_ = JavaObjectWeakGlobalRef(env, object);
}

StoragePartition* AwQuotaManagerBridgeImpl::GetStoragePartition() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // AndroidWebview does not use per-site storage partitions.
  StoragePartition* storage_partition =
      content::BrowserContext::GetDefaultStoragePartition(browser_context_);
  DCHECK(storage_partition);
  return storage_partition;
}

QuotaManager* AwQuotaManagerBridgeImpl::GetQuotaManager() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  QuotaManager* quota_manager = GetStoragePartition()->GetQuotaManager();
  DCHECK(quota_manager);
  return quota_manager;
}

void AwQuotaManagerBridgeImpl::DeleteAllData(JNIEnv* env, jobject object) {
  RunOnUIThread(base::Bind(&AwQuotaManagerBridgeImpl::DeleteAllDataOnUiThread,
                           this));
}

void AwQuotaManagerBridgeImpl::DeleteAllDataOnUiThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  GetStoragePartition()->ClearDataForUnboundedRange(
      // Clear all web storage data except cookies.
      StoragePartition::REMOVE_DATA_MASK_APPCACHE |
          StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
          StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
          StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE |
          StoragePartition::REMOVE_DATA_MASK_WEBSQL,
      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY);
}

void AwQuotaManagerBridgeImpl::DeleteOrigin(
    JNIEnv* env, jobject object, jstring origin) {
  base::string16 origin_string(
      base::android::ConvertJavaStringToUTF16(env, origin));
  RunOnUIThread(base::Bind(&AwQuotaManagerBridgeImpl::DeleteOriginOnUiThread,
                           this,
                           origin_string));
}

void AwQuotaManagerBridgeImpl::DeleteOriginOnUiThread(
    const base::string16& origin) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  StoragePartition* storage_partition = GetStoragePartition();
  storage_partition->ClearDataForOrigin(
      // All (temporary) QuotaClient types.
      StoragePartition::REMOVE_DATA_MASK_APPCACHE |
          StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
          StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
          StoragePartition::REMOVE_DATA_MASK_WEBSQL,
      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY,
      GURL(origin),
      storage_partition->GetURLRequestContext());
}

void AwQuotaManagerBridgeImpl::GetOrigins(
    JNIEnv* env, jobject object, jint callback_id) {
  RunOnUIThread(base::Bind(&AwQuotaManagerBridgeImpl::GetOriginsOnUiThread,
                           this,
                           callback_id));
}

void AwQuotaManagerBridgeImpl::GetOriginsOnUiThread(jint callback_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  const GetOriginsCallback ui_callback = base::Bind(
      &AwQuotaManagerBridgeImpl::GetOriginsCallbackImpl,
      weak_factory_.GetWeakPtr(),
      callback_id);

  (new GetOriginsTask(ui_callback, GetQuotaManager()))->Run();
}

void AwQuotaManagerBridgeImpl::GetOriginsCallbackImpl(
    int jcallback_id,
    const std::vector<std::string>& origin,
    const std::vector<int64>& usage,
    const std::vector<int64>& quota) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
  if (obj.is_null())
    return;

  Java_AwQuotaManagerBridge_onGetOriginsCallback(
      env,
      obj.obj(),
      jcallback_id,
      base::android::ToJavaArrayOfStrings(env, origin).obj(),
      base::android::ToJavaLongArray(env, usage).obj(),
      base::android::ToJavaLongArray(env, quota).obj());
}

namespace {

void OnUsageAndQuotaObtained(
    const AwQuotaManagerBridgeImpl::QuotaUsageCallback& ui_callback,
    quota::QuotaStatusCode status_code,
    int64 usage,
    int64 quota) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (status_code != quota::kQuotaStatusOk) {
    usage = 0;
    quota = 0;
  }
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      base::Bind(ui_callback, usage, quota));
}

} // namespace

void AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOrigin(
    JNIEnv* env, jobject object,
    jstring origin,
    jint callback_id,
    bool is_quota) {
  base::string16 origin_string(
      base::android::ConvertJavaStringToUTF16(env, origin));
  RunOnUIThread(base::Bind(
      &AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOriginOnUiThread,
      this,
      origin_string,
      callback_id,
      is_quota));
}

void AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOriginOnUiThread(
    const base::string16& origin,
    jint callback_id,
    bool is_quota) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  const QuotaUsageCallback ui_callback = base::Bind(
      &AwQuotaManagerBridgeImpl::QuotaUsageCallbackImpl,
      weak_factory_.GetWeakPtr(),
      callback_id,
      is_quota);

  BrowserThread::PostTask(
      BrowserThread::IO,
      FROM_HERE,
      base::Bind(&QuotaManager::GetUsageAndQuota,
                 GetQuotaManager(),
                 GURL(origin),
                 quota::kStorageTypeTemporary,
                 base::Bind(&OnUsageAndQuotaObtained, ui_callback)));
}

void AwQuotaManagerBridgeImpl::QuotaUsageCallbackImpl(
    int jcallback_id, bool is_quota, int64 usage, int64 quota) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
  if (obj.is_null())
    return;

  Java_AwQuotaManagerBridge_onGetUsageAndQuotaForOriginCallback(
      env, obj.obj(), jcallback_id, is_quota, usage, quota);
}

bool RegisterAwQuotaManagerBridge(JNIEnv* env) {
  return RegisterNativesImpl(env) >= 0;
}

}  // namespace android_webview
