[sql] Retry Open() if error handler fixed things.

Since the caller cannot have existing database-derived state before
the database is opened, Open() can be safely retried after the error
handler has razed the database.

BUG=109482

Review URL: https://chromiumcodereview.appspot.com/18641004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@211936 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/sql/connection.cc b/sql/connection.cc
index 5f76a7f3..95d09c2 100644
--- a/sql/connection.cc
+++ b/sql/connection.cc
@@ -194,15 +194,15 @@
   }
 
 #if defined(OS_WIN)
-  return OpenInternal(WideToUTF8(path.value()));
+  return OpenInternal(WideToUTF8(path.value()), RETRY_ON_POISON);
 #elif defined(OS_POSIX)
-  return OpenInternal(path.value());
+  return OpenInternal(path.value(), RETRY_ON_POISON);
 #endif
 }
 
 bool Connection::OpenInMemory() {
   in_memory_ = true;
-  return OpenInternal(":memory:");
+  return OpenInternal(":memory:", NO_RETRY);
 }
 
 void Connection::CloseInternal(bool forced) {
@@ -238,8 +238,8 @@
     AssertIOAllowed();
     // TODO(shess): Histogram for failure.
     sqlite3_close(db_);
-    db_ = NULL;
   }
+  db_ = NULL;
 }
 
 void Connection::Close() {
@@ -699,7 +699,8 @@
   return sqlite3_errmsg(db_);
 }
 
-bool Connection::OpenInternal(const std::string& file_name) {
+bool Connection::OpenInternal(const std::string& file_name,
+                              Connection::Retry retry_flag) {
   AssertIOAllowed();
 
   if (db_) {
@@ -723,8 +724,11 @@
     UMA_HISTOGRAM_ENUMERATION("Sqlite.OpenFailure", err & 0xff, 50);
 
     OnSqliteError(err, NULL);
+    bool was_poisoned = poisoned_;
     Close();
-    db_ = NULL;
+
+    if (was_poisoned && retry_flag == RETRY_ON_POISON)
+      return OpenInternal(file_name, NO_RETRY);
     return false;
   }
 
@@ -806,7 +810,10 @@
   }
 
   if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) {
+    bool was_poisoned = poisoned_;
     Close();
+    if (was_poisoned && retry_flag == RETRY_ON_POISON)
+      return OpenInternal(file_name, NO_RETRY);
     return false;
   }