Index: content/browser/indexed_db/indexed_db_browsertest.cc |
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc |
index 5a2389333516c899ec373d118fcb7d21d26a0aa6..414f26600a75c85fced586d07665c83a97c2d4a7 100644 |
--- a/content/browser/indexed_db/indexed_db_browsertest.cc |
+++ b/content/browser/indexed_db/indexed_db_browsertest.cc |
@@ -5,6 +5,7 @@ |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/file_util.h" |
+#include "base/files/file_enumerator.h" |
#include "base/files/file_path.h" |
#include "base/memory/ref_counted.h" |
#include "base/message_loop/message_loop.h" |
@@ -24,6 +25,10 @@ |
#include "content/shell/browser/shell.h" |
#include "content/test/content_browser_test.h" |
#include "content/test/content_browser_test_utils.h" |
+#include "net/base/net_errors.h" |
+#include "net/test/embedded_test_server/embedded_test_server.h" |
+#include "net/test/embedded_test_server/http_request.h" |
+#include "net/test/embedded_test_server/http_response.h" |
#include "webkit/browser/database/database_util.h" |
#include "webkit/browser/quota/quota_manager.h" |
@@ -356,6 +361,134 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) { |
SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html")); |
} |
+namespace { |
+ |
+static void CompactIndexedDBBackingStore( |
+ scoped_refptr<IndexedDBContextImpl> context, |
+ const GURL& origin_url) { |
+ IndexedDBFactory* factory = context->GetIDBFactory(); |
+ |
+ std::pair<IndexedDBFactory::OriginDBMapIterator, |
+ IndexedDBFactory::OriginDBMapIterator> range = |
+ factory->GetOpenDatabasesForOrigin(origin_url); |
+ |
+ if (range.first == range.second) // If no open db's for this origin |
+ return; |
+ |
+ // Compact the first db's backing store since all the db's are in the same |
+ // backing store. |
+ IndexedDBDatabase* db = range.first->second; |
+ IndexedDBBackingStore* backing_store = db->backing_store(); |
+ backing_store->Compact(); |
+} |
+ |
+static void CorruptIndexedDBDatabase( |
+ IndexedDBContextImpl* context, |
+ const GURL& origin_url, |
+ base::WaitableEvent* signal_when_finished) { |
+ |
+ CompactIndexedDBBackingStore(context, origin_url); |
+ |
+ int numFiles = 0; |
+ int numErrors = 0; |
+ base::FilePath idb_data_path = context->GetFilePath(origin_url); |
+ const bool recursive = false; |
+ base::FileEnumerator enumerator( |
+ idb_data_path, recursive, base::FileEnumerator::FILES); |
+ for (base::FilePath idb_file = enumerator.Next(); !idb_file.empty(); |
+ idb_file = enumerator.Next()) { |
+ int64 size(0); |
+ GetFileSize(idb_file, &size); |
+ |
+ if (idb_file.Extension() == ".ldb") { |
+ numFiles++; |
+ base::ScopedFILE f(base::OpenFile(idb_file, "w")); |
+ if (f) { |
+ char zero(0); |
+ if (size != (int64)fwrite(&zero, sizeof(zero), size, f.get())) |
+ numErrors++; |
+ } else { |
+ numErrors++; |
+ } |
+ } |
+ } |
+ |
+ VLOG(0) << "There were " << numFiles << " in " << idb_data_path.value() |
+ << " with " << numErrors << " errors"; |
+ signal_when_finished->Signal(); |
+} |
+ |
+const std::string s_corrupt_db_test_prefix = "/corrupt/test/"; |
+ |
+static scoped_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler( |
+ IndexedDBContextImpl* context, |
+ const GURL& origin_url, |
+ const std::string& path, |
+ const net::test_server::HttpRequest& request) { |
+ |
+ std::string request_path; |
+ if (path.find(s_corrupt_db_test_prefix) != std::string::npos) |
+ request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size()); |
+ else |
+ return scoped_ptr<net::test_server::HttpResponse>(); |
+ |
+ // Remove the query string if present. |
+ std::string request_query; |
+ size_t query_pos = request_path.find('?'); |
+ if (query_pos != std::string::npos) { |
+ request_query = request_path.substr(query_pos + 1); |
+ request_path = request_path.substr(0, query_pos); |
+ } |
+ |
+ if (request_path == "corruptdb" && !request_query.empty()) { |
+ VLOG(0) << "Requested to corrupt IndexedDB: " << request_query; |
+ base::WaitableEvent signal_when_finished(false, false); |
+ context->TaskRunner()->PostTask(FROM_HERE, |
+ base::Bind(&CorruptIndexedDBDatabase, |
+ base::ConstRef(context), |
+ origin_url, |
+ &signal_when_finished)); |
+ signal_when_finished.Wait(); |
+ |
+ scoped_ptr<net::test_server::BasicHttpResponse> http_response( |
+ new net::test_server::BasicHttpResponse); |
+ http_response->set_code(net::HTTP_OK); |
+ return http_response.PassAs<net::test_server::HttpResponse>(); |
+ } |
+ |
+ // A request for a test resource |
+ base::FilePath resourcePath = |
+ content::GetTestFilePath("indexeddb", request_path.c_str()); |
+ scoped_ptr<net::test_server::BasicHttpResponse> http_response( |
+ new net::test_server::BasicHttpResponse); |
+ http_response->set_code(net::HTTP_OK); |
+ std::string file_contents; |
+ if (!base::ReadFileToString(resourcePath, &file_contents)) |
+ return scoped_ptr<net::test_server::HttpResponse>(); |
+ http_response->set_content(file_contents); |
+ return http_response.PassAs<net::test_server::HttpResponse>(); |
+} |
+ |
+} // namespace |
+ |
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CorruptedOpenDatabase) { |
+ ASSERT_TRUE(embedded_test_server()->Started() || |
+ embedded_test_server()->InitializeAndWaitUntilReady()); |
+ const GURL& origin_url = embedded_test_server()->base_url(); |
+ embedded_test_server()->RegisterRequestHandler( |
+ base::Bind(&CorruptDBRequestHandler, |
+ base::ConstRef(GetContext()), |
+ origin_url, |
+ s_corrupt_db_test_prefix)); |
+ |
+ std::string test_file = |
+ s_corrupt_db_test_prefix + "corrupted_open_db_detection.html"; |
+ SimpleTest(embedded_test_server()->GetURL(test_file)); |
+ |
+ test_file = s_corrupt_db_test_prefix + "corrupted_open_db_recovery.html"; |
+ SimpleTest(embedded_test_server()->GetURL(test_file)); |
+} |
+ |
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) { |
const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html"); |
SimpleTest(GURL(test_url.spec() + "#fill")); |
@@ -449,6 +582,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) { |
base::string16 expected_title16(ASCIIToUTF16("connection closed")); |
TitleWatcher title_watcher(shell()->web_contents(), expected_title16); |
+ title_watcher.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error")); |
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); |
} |