| 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 478a07b8237897c6f70f01ff61f7af224e747f7c..79ed82e1576bb3df37ea46a4821b06841cf47182 100644
|
| --- a/content/browser/indexed_db/indexed_db_browsertest.cc
|
| +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
|
| @@ -5,9 +5,11 @@
|
| #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"
|
| +#include "base/platform_file.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/test/thread_test_helper.h"
|
| #include "content/browser/browser_main_loop.h"
|
| @@ -24,6 +26,10 @@
|
| #include "content/public/test/content_browser_test.h"
|
| #include "content/public/test/content_browser_test_utils.h"
|
| #include "content/shell/browser/shell.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 +362,140 @@ 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() == FILE_PATH_LITERAL(".ldb")) {
|
| + numFiles++;
|
| + base::PlatformFile f = base::CreatePlatformFile(
|
| + idb_file,
|
| + base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_OPEN_TRUNCATED,
|
| + NULL,
|
| + NULL);
|
| + if (f) {
|
| + // Was opened truncated, expand back to the original
|
| + // file size and fill with zeros (corrupting the file).
|
| + base::TruncatePlatformFile(f, size);
|
| + if (!base::ClosePlatformFile(f))
|
| + 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 +589,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());
|
| }
|
|
|
|
|