WebSQL: Initialize SQLite via //sql.

Chrome uses SQLite via the high-level API in //sql, with the notable
exception of Blink's WebSQL implementation. This is for historical
reasons -- WebSQL was implemented before the Blink/WebKit fork, so it
was unacceptable for the WebSQL implementation to depend on code in the
Chromium source tree.

In the long run (assuming that WebSQL doesn't go away completely) we
want WebSQL to also use SQLite via //sql. This CL makes the first step,
by routing SQLite initialization via //sql, instead of calling the
library directly.

This CL also fixes up Blink's dependencies on SQLite. Blink core does
not depend on SQLite, and the only module depending on it is WebSQL.

Bug: 807093
Change-Id: Iae6a02e5b0488051853f75dcb397e7c68ffc961b
Reviewed-on: https://chromium-review.googlesource.com/894692
Commit-Queue: Victor Costan <[email protected]>
Reviewed-by: Chris Mumford <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: Kentaro Hara <[email protected]>
Cr-Commit-Position: refs/heads/master@{#535528}
diff --git a/sql/connection.cc b/sql/connection.cc
index 76f9371..4fd3d41 100644
--- a/sql/connection.cc
+++ b/sql/connection.cc
@@ -11,29 +11,28 @@
 
 #include <utility>
 
-#include "base/bind.h"
 #include "base/debug/alias.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/format_macros.h"
 #include "base/json/json_file_value_serializer.h"
-#include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
+#include "base/no_destructor.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "build/build_config.h"
 #include "sql/connection_memory_dump_provider.h"
+#include "sql/initialization.h"
 #include "sql/meta_table.h"
 #include "sql/statement.h"
 #include "sql/vfs_wrapper.h"
@@ -130,62 +129,6 @@
   return true;
 }
 
-void RecordSqliteMemory10Min() {
-  const int64_t used = sqlite3_memory_used();
-  UMA_HISTOGRAM_COUNTS("Sqlite.MemoryKB.TenMinutes", used / 1024);
-}
-
-void RecordSqliteMemoryHour() {
-  const int64_t used = sqlite3_memory_used();
-  UMA_HISTOGRAM_COUNTS("Sqlite.MemoryKB.OneHour", used / 1024);
-}
-
-void RecordSqliteMemoryDay() {
-  const int64_t used = sqlite3_memory_used();
-  UMA_HISTOGRAM_COUNTS("Sqlite.MemoryKB.OneDay", used / 1024);
-}
-
-void RecordSqliteMemoryWeek() {
-  const int64_t used = sqlite3_memory_used();
-  UMA_HISTOGRAM_COUNTS("Sqlite.MemoryKB.OneWeek", used / 1024);
-}
-
-// SQLite automatically calls sqlite3_initialize() lazily, but
-// sqlite3_initialize() uses double-checked locking and thus can have
-// data races.
-//
-// TODO(shess): Another alternative would be to have
-// sqlite3_initialize() called as part of process bring-up.  If this
-// is changed, remove the dynamic_annotations dependency in sql.gyp.
-base::LazyInstance<base::Lock>::Leaky
-    g_sqlite_init_lock = LAZY_INSTANCE_INITIALIZER;
-void InitializeSqlite() {
-  base::AutoLock lock(g_sqlite_init_lock.Get());
-  static bool first_call = true;
-  if (first_call) {
-    sqlite3_initialize();
-
-    // Schedule callback to record memory footprint histograms at 10m, 1h, and
-    // 1d. There may not be a registered task runner in tests.
-    if (base::SequencedTaskRunnerHandle::IsSet()) {
-      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, base::Bind(&RecordSqliteMemory10Min),
-          base::TimeDelta::FromMinutes(10));
-      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, base::Bind(&RecordSqliteMemoryHour),
-          base::TimeDelta::FromHours(1));
-      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, base::Bind(&RecordSqliteMemoryDay),
-          base::TimeDelta::FromDays(1));
-      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, base::Bind(&RecordSqliteMemoryWeek),
-          base::TimeDelta::FromDays(7));
-    }
-
-    first_call = false;
-  }
-}
-
 // Helper to get the sqlite3_file* associated with the "main" database.
 int GetSqlite3File(sqlite3* db, sqlite3_file** file) {
   *file = NULL;
@@ -642,7 +585,8 @@
   // is _probably_ something systemic wrong with the user's system.  So the lock
   // should never be contended, but when it is the database experience is
   // already bad.
-  base::AutoLock lock(g_sqlite_init_lock.Get());
+  static base::NoDestructor<base::Lock> lock;
+  base::AutoLock auto_lock(*lock);
 
   std::unique_ptr<base::Value> root;
   if (!base::PathExists(breadcrumb_path)) {
@@ -951,7 +895,8 @@
     if (amount < 0)
       amount = 0;
     if (amount > 0) {
-      base::AutoLock lock(g_sqlite_init_lock.Get());
+      static base::NoDestructor<base::Lock> lock;
+      base::AutoLock auto_lock(*lock);
       static sqlite3_int64 g_reads_allowed = 20 * 1024 * 1024;
       if (g_reads_allowed < amount)
         amount = g_reads_allowed;
@@ -1220,8 +1165,7 @@
   std::string wal_str = AsUTF8ForSQL(wal_path);
   std::string path_str = AsUTF8ForSQL(path);
 
-  // Make sure sqlite3_initialize() is called before anything else.
-  InitializeSqlite();
+  EnsureSqliteInitialized();
 
   sqlite3_vfs* vfs = sqlite3_vfs_find(NULL);
   CHECK(vfs);
@@ -1645,8 +1589,7 @@
     return false;
   }
 
-  // Make sure sqlite3_initialize() is called before anything else.
-  InitializeSqlite();
+  EnsureSqliteInitialized();
 
   // Setup the stats histograms immediately rather than allocating lazily.
   // Connections which won't exercise all of these probably shouldn't exist.