// Copyright 2017 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 "content/browser/renderer_host/web_database_host_impl.h"

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/origin_util.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "storage/browser/database/database_util.h"
#include "storage/browser/database/vfs_backend.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/origin.h"

using storage::DatabaseUtil;
using storage::VfsBackend;
using storage::QuotaManager;

namespace content {
namespace {
// The number of times to attempt to delete the SQLite database, if there is
// an error.
const int kNumDeleteRetries = 2;
// The delay between each retry to delete the SQLite database.
const int kDelayDeleteRetryMs = 100;

void ValidateOriginOnUIThread(
    int process_id,
    const url::Origin& origin,
    scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
    base::OnceClosure success_callback,
    mojo::ReportBadMessageCallback error_callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Return early if the process was shutdown before this task was able to run.
  if (!RenderProcessHost::FromID(process_id))
    return;

  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
          process_id, origin)) {
    callback_task_runner->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(error_callback), "Unauthorized origin."));
    return;
  }

  callback_task_runner->PostTask(FROM_HERE, std::move(success_callback));
}

}  // namespace

WebDatabaseHostImpl::WebDatabaseHostImpl(
    int process_id,
    scoped_refptr<storage::DatabaseTracker> db_tracker)
    : process_id_(process_id),
      observer_added_(false),
      db_tracker_(std::move(db_tracker)),
      weak_ptr_factory_(this) {
  DCHECK(db_tracker_);
}

WebDatabaseHostImpl::~WebDatabaseHostImpl() {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  if (observer_added_) {
    db_tracker_->RemoveObserver(this);

    // If the renderer process died without closing all databases,
    // then we need to manually close those connections
    db_tracker_->CloseDatabases(database_connections_);
    database_connections_.RemoveAllConnections();
  }
}

void WebDatabaseHostImpl::Create(
    int process_id,
    scoped_refptr<storage::DatabaseTracker> db_tracker,
    blink::mojom::WebDatabaseHostRequest request) {
  DCHECK(db_tracker->task_runner()->RunsTasksInCurrentSequence());
  mojo::MakeStrongBinding(
      std::make_unique<WebDatabaseHostImpl>(process_id, std::move(db_tracker)),
      std::move(request));
}

void WebDatabaseHostImpl::OpenFile(const base::string16& vfs_file_name,
                                   int32_t desired_flags,
                                   OpenFileCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  ValidateOrigin(vfs_file_name,
                 base::BindOnce(&WebDatabaseHostImpl::OpenFileValidated,
                                weak_ptr_factory_.GetWeakPtr(), vfs_file_name,
                                desired_flags, std::move(callback)));
}

void WebDatabaseHostImpl::OpenFileValidated(const base::string16& vfs_file_name,
                                            int32_t desired_flags,
                                            OpenFileCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  base::File file;
  const base::File* tracked_file = nullptr;
  std::string origin_identifier;
  base::string16 database_name;

  // When in incognito mode, we want to make sure that all DB files are
  // removed when the incognito browser context goes away, so we add the
  // SQLITE_OPEN_DELETEONCLOSE flag when opening all files, and keep
  // open handles to them in the database tracker to make sure they're
  // around for as long as needed.
  if (vfs_file_name.empty()) {
    file = VfsBackend::OpenTempFileInDirectory(
        db_tracker_->database_directory(), desired_flags);
  } else if (DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
                                            &database_name, nullptr) &&
             !db_tracker_->IsDatabaseScheduledForDeletion(origin_identifier,
                                                          database_name)) {
    base::FilePath db_file = DatabaseUtil::GetFullFilePathForVfsFile(
        db_tracker_.get(), vfs_file_name);
    if (!db_file.empty()) {
      if (db_tracker_->IsIncognitoProfile()) {
        tracked_file = db_tracker_->GetIncognitoFile(vfs_file_name);
        if (!tracked_file) {
          file = VfsBackend::OpenFile(
              db_file, desired_flags | SQLITE_OPEN_DELETEONCLOSE);
          if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE)) {
            tracked_file =
                db_tracker_->SaveIncognitoFile(vfs_file_name, std::move(file));
          }
        }
      } else {
        file = VfsBackend::OpenFile(db_file, desired_flags);
      }
    }
  }

  base::File result;
  if (file.IsValid()) {
    result = std::move(file);
  } else if (tracked_file) {
    DCHECK(tracked_file->IsValid());
    result = tracked_file->Duplicate();
  }
  std::move(callback).Run(std::move(result));
}

void WebDatabaseHostImpl::DeleteFile(const base::string16& vfs_file_name,
                                     bool sync_dir,
                                     DeleteFileCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  ValidateOrigin(
      vfs_file_name,
      base::BindOnce(&WebDatabaseHostImpl::DatabaseDeleteFile,
                     weak_ptr_factory_.GetWeakPtr(), vfs_file_name, sync_dir,
                     std::move(callback), kNumDeleteRetries));
}

void WebDatabaseHostImpl::GetFileAttributes(
    const base::string16& vfs_file_name,
    GetFileAttributesCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  ValidateOrigin(
      vfs_file_name,
      base::BindOnce(&WebDatabaseHostImpl::GetFileAttributesValidated,
                     weak_ptr_factory_.GetWeakPtr(), vfs_file_name,
                     std::move(callback)));
}

void WebDatabaseHostImpl::GetFileAttributesValidated(
    const base::string16& vfs_file_name,
    GetFileAttributesCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  int32_t attributes = -1;
  base::FilePath db_file =
      DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
  if (!db_file.empty()) {
    attributes = VfsBackend::GetFileAttributes(db_file);
  }
  std::move(callback).Run(attributes);
}

void WebDatabaseHostImpl::GetFileSize(const base::string16& vfs_file_name,
                                      GetFileSizeCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  ValidateOrigin(vfs_file_name,
                 base::BindOnce(&WebDatabaseHostImpl::GetFileSizeValidated,
                                weak_ptr_factory_.GetWeakPtr(), vfs_file_name,
                                std::move(callback)));
}

void WebDatabaseHostImpl::GetFileSizeValidated(
    const base::string16& vfs_file_name,
    GetFileSizeCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  int64_t size = 0LL;
  base::FilePath db_file =
      DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
  if (!db_file.empty()) {
    size = VfsBackend::GetFileSize(db_file);
  }
  std::move(callback).Run(size);
}

void WebDatabaseHostImpl::SetFileSize(const base::string16& vfs_file_name,
                                      int64_t expected_size,
                                      SetFileSizeCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  ValidateOrigin(vfs_file_name,
                 base::BindOnce(&WebDatabaseHostImpl::SetFileSizeValidated,
                                weak_ptr_factory_.GetWeakPtr(), vfs_file_name,
                                expected_size, std::move(callback)));
}

void WebDatabaseHostImpl::SetFileSizeValidated(
    const base::string16& vfs_file_name,
    int64_t expected_size,
    SetFileSizeCallback callback) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  bool success = false;
  base::FilePath db_file =
      DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
  if (!db_file.empty()) {
    success = VfsBackend::SetFileSize(db_file, expected_size);
  }
  std::move(callback).Run(success);
}

void WebDatabaseHostImpl::GetSpaceAvailable(
    const url::Origin& origin,
    GetSpaceAvailableCallback callback) {
  // QuotaManager is only available on the IO thread.
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  ValidateOrigin(
      origin, base::BindOnce(&WebDatabaseHostImpl::GetSpaceAvailableValidated,
                             weak_ptr_factory_.GetWeakPtr(), origin,
                             std::move(callback)));
}

void WebDatabaseHostImpl::GetSpaceAvailableValidated(
    const url::Origin& origin,
    GetSpaceAvailableCallback callback) {
  // QuotaManager is only available on the IO thread.
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  DCHECK(db_tracker_->quota_manager_proxy());
  db_tracker_->quota_manager_proxy()->GetUsageAndQuota(
      db_tracker_->task_runner(), origin, blink::mojom::StorageType::kTemporary,
      base::BindOnce(
          [](GetSpaceAvailableCallback callback,
             blink::mojom::QuotaStatusCode status, int64_t usage,
             int64_t quota) {
            int64_t available = 0;
            if ((status == blink::mojom::QuotaStatusCode::kOk) &&
                (usage < quota)) {
              available = quota - usage;
            }
            std::move(callback).Run(available);
          },
          std::move(callback)));
}

void WebDatabaseHostImpl::DatabaseDeleteFile(
    const base::string16& vfs_file_name,
    bool sync_dir,
    DeleteFileCallback callback,
    int reschedule_count) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  // Return an error if the file name is invalid or if the file could not
  // be deleted after kNumDeleteRetries attempts.
  int error_code = SQLITE_IOERR_DELETE;
  base::FilePath db_file =
      DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
  if (!db_file.empty()) {
    // In order to delete a journal file in incognito mode, we only need to
    // close the open handle to it that's stored in the database tracker.
    if (db_tracker_->IsIncognitoProfile()) {
      const base::string16 wal_suffix(base::ASCIIToUTF16("-wal"));
      base::string16 sqlite_suffix;

      // WAL files can be deleted without having previously been opened.
      if (!db_tracker_->HasSavedIncognitoFileHandle(vfs_file_name) &&
          DatabaseUtil::CrackVfsFileName(vfs_file_name, nullptr, nullptr,
                                         &sqlite_suffix) &&
          sqlite_suffix == wal_suffix) {
        error_code = SQLITE_OK;
      } else {
        db_tracker_->CloseIncognitoFileHandle(vfs_file_name);
        error_code = SQLITE_OK;
      }
    } else {
      error_code = VfsBackend::DeleteFile(db_file, sync_dir);
    }

    if ((error_code == SQLITE_IOERR_DELETE) && reschedule_count) {
      // If the file could not be deleted, try again.
      db_tracker_->task_runner()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&WebDatabaseHostImpl::DatabaseDeleteFile,
                         weak_ptr_factory_.GetWeakPtr(), vfs_file_name,
                         sync_dir, std::move(callback), reschedule_count - 1),
          base::TimeDelta::FromMilliseconds(kDelayDeleteRetryMs));
      return;
    }
  }

  std::move(callback).Run(error_code);
}

void WebDatabaseHostImpl::Opened(const url::Origin& origin,
                                 const base::string16& database_name,
                                 const base::string16& database_description,
                                 int64_t estimated_size) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  if (!observer_added_) {
    observer_added_ = true;
    db_tracker_->AddObserver(this);
  }

  ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::OpenedValidated,
                                        weak_ptr_factory_.GetWeakPtr(), origin,
                                        database_name, database_description,
                                        estimated_size));
}

void WebDatabaseHostImpl::OpenedValidated(
    const url::Origin& origin,
    const base::string16& database_name,
    const base::string16& database_description,
    int64_t estimated_size) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  UMA_HISTOGRAM_BOOLEAN("websql.OpenDatabase", IsOriginSecure(origin.GetURL()));

  int64_t database_size = 0;
  std::string origin_identifier(storage::GetIdentifierFromOrigin(origin));
  db_tracker_->DatabaseOpened(origin_identifier, database_name,
                              database_description, estimated_size,
                              &database_size);

  database_connections_.AddConnection(origin_identifier, database_name);

  GetWebDatabase().UpdateSize(origin, database_name, database_size);
}

void WebDatabaseHostImpl::Modified(const url::Origin& origin,
                                   const base::string16& database_name) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::ModifiedValidated,
                                        weak_ptr_factory_.GetWeakPtr(), origin,
                                        database_name));
}

void WebDatabaseHostImpl::ModifiedValidated(
    const url::Origin& origin,
    const base::string16& database_name) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  std::string origin_identifier(storage::GetIdentifierFromOrigin(origin));
  if (!database_connections_.IsDatabaseOpened(origin_identifier,
                                              database_name)) {
    mojo::ReportBadMessage("Database not opened on modify");
    return;
  }

  db_tracker_->DatabaseModified(origin_identifier, database_name);
}

void WebDatabaseHostImpl::Closed(const url::Origin& origin,
                                 const base::string16& database_name) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::ClosedValidated,
                                        weak_ptr_factory_.GetWeakPtr(), origin,
                                        database_name));
}

void WebDatabaseHostImpl::ClosedValidated(const url::Origin& origin,
                                          const base::string16& database_name) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  std::string origin_identifier(storage::GetIdentifierFromOrigin(origin));
  if (!database_connections_.IsDatabaseOpened(origin_identifier,
                                              database_name)) {
    mojo::ReportBadMessage("Database not opened on close");
    return;
  }

  database_connections_.RemoveConnection(origin_identifier, database_name);
  db_tracker_->DatabaseClosed(origin_identifier, database_name);
}

void WebDatabaseHostImpl::HandleSqliteError(const url::Origin& origin,
                                            const base::string16& database_name,
                                            int32_t error) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  ValidateOrigin(
      origin,
      base::BindOnce(&storage::DatabaseTracker::HandleSqliteError, db_tracker_,
                     storage::GetIdentifierFromOrigin(origin), database_name,
                     error));
}

void WebDatabaseHostImpl::OnDatabaseSizeChanged(
    const std::string& origin_identifier,
    const base::string16& database_name,
    int64_t database_size) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  if (!database_connections_.IsOriginUsed(origin_identifier)) {
    return;
  }

  GetWebDatabase().UpdateSize(
      storage::GetOriginFromIdentifier(origin_identifier), database_name,
      database_size);
}

void WebDatabaseHostImpl::OnDatabaseScheduledForDeletion(
    const std::string& origin_identifier,
    const base::string16& database_name) {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());

  GetWebDatabase().CloseImmediately(
      storage::GetOriginFromIdentifier(origin_identifier), database_name);
}

blink::mojom::WebDatabase& WebDatabaseHostImpl::GetWebDatabase() {
  DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
  if (!database_provider_) {
    // The interface binding needs to occur on the UI thread, as we can
    // only call RenderProcessHost::FromID() on the UI thread.
    base::PostTaskWithTraits(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(
            [](int process_id, blink::mojom::WebDatabaseRequest request) {
              RenderProcessHost* host = RenderProcessHost::FromID(process_id);
              if (host) {
                content::BindInterface(host, std::move(request));
              }
            },
            process_id_, mojo::MakeRequest(&database_provider_)));
  }
  return *database_provider_;
}

void WebDatabaseHostImpl::ValidateOrigin(const url::Origin& origin,
                                         base::OnceClosure callback) {
  if (origin.opaque()) {
    mojo::ReportBadMessage("Invalid origin.");
    return;
  }

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&ValidateOriginOnUIThread, process_id_, origin,
                     base::RetainedRef(db_tracker_->task_runner()),
                     std::move(callback), mojo::GetBadMessageCallback()));
}

void WebDatabaseHostImpl::ValidateOrigin(const base::string16& vfs_file_name,
                                         base::OnceClosure callback) {
  std::string origin_identifier;
  if (vfs_file_name.empty()) {
    std::move(callback).Run();
    return;
  }

  if (!DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
                                      nullptr, nullptr)) {
    std::move(callback).Run();
    return;
  }

  ValidateOrigin(storage::GetOriginFromIdentifier(origin_identifier),
                 std::move(callback));
}

}  // namespace content
