1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "base/command_line.h"
7 #include "base/file_util.h"
8 #include "base/files/file.h"
9 #include "base/files/file_enumerator.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/test/thread_test_helper.h"
15 #include "content/browser/browser_main_loop.h"
16 #include "content/browser/indexed_db/indexed_db_context_impl.h"
17 #include "content/browser/web_contents/web_contents_impl.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/storage_partition.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/content_switches.h"
24 #include "content/public/common/url_constants.h"
25 #include "content/public/test/browser_test_utils.h"
26 #include "content/public/test/content_browser_test.h"
27 #include "content/public/test/content_browser_test_utils.h"
28 #include "content/shell/browser/shell.h"
29 #include "net/base/net_errors.h"
30 #include "net/test/embedded_test_server/embedded_test_server.h"
31 #include "net/test/embedded_test_server/http_request.h"
32 #include "net/test/embedded_test_server/http_response.h"
33 #include "webkit/browser/database/database_util.h"
34 #include "webkit/browser/quota/quota_manager.h"
36 using base::ASCIIToUTF16
;
37 using quota::QuotaManager
;
38 using webkit_database::DatabaseUtil
;
42 // This browser test is aimed towards exercising the IndexedDB bindings and
43 // the actual implementation that lives in the browser side.
44 class IndexedDBBrowserTest
: public ContentBrowserTest
{
46 IndexedDBBrowserTest() : disk_usage_(-1) {}
48 void SimpleTest(const GURL
& test_url
, bool incognito
= false) {
49 // The test page will perform tests on IndexedDB, then navigate to either
50 // a #pass or #fail ref.
51 Shell
* the_browser
= incognito
? CreateOffTheRecordBrowser() : shell();
53 VLOG(0) << "Navigating to URL and blocking.";
54 NavigateToURLBlockUntilNavigationsComplete(the_browser
, test_url
, 2);
55 VLOG(0) << "Navigation done.";
57 the_browser
->web_contents()->GetLastCommittedURL().ref();
58 if (result
!= "pass") {
59 std::string js_result
;
60 ASSERT_TRUE(ExecuteScriptAndExtractString(
61 the_browser
->web_contents(),
62 "window.domAutomationController.send(getLog())",
64 FAIL() << "Failed: " << js_result
;
68 void NavigateAndWaitForTitle(Shell
* shell
,
71 const char* expected_string
) {
72 GURL url
= GetTestUrl("indexeddb", filename
);
74 url
= GURL(url
.spec() + hash
);
76 base::string16
expected_title16(ASCIIToUTF16(expected_string
));
77 TitleWatcher
title_watcher(shell
->web_contents(), expected_title16
);
78 NavigateToURL(shell
, url
);
79 EXPECT_EQ(expected_title16
, title_watcher
.WaitAndGetTitle());
82 IndexedDBContextImpl
* GetContext() {
83 StoragePartition
* partition
=
84 BrowserContext::GetDefaultStoragePartition(
85 shell()->web_contents()->GetBrowserContext());
86 return static_cast<IndexedDBContextImpl
*>(partition
->GetIndexedDBContext());
89 void SetQuota(int quotaKilobytes
) {
90 const int kTemporaryStorageQuotaSize
= quotaKilobytes
91 * 1024 * QuotaManager::kPerHostTemporaryPortion
;
92 SetTempQuota(kTemporaryStorageQuotaSize
,
93 BrowserContext::GetDefaultStoragePartition(
94 shell()->web_contents()->GetBrowserContext())->GetQuotaManager());
97 static void SetTempQuota(int64 bytes
, scoped_refptr
<QuotaManager
> qm
) {
98 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
99 BrowserThread::PostTask(
100 BrowserThread::IO
, FROM_HERE
,
101 base::Bind(&IndexedDBBrowserTest::SetTempQuota
, bytes
, qm
));
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
105 qm
->SetTemporaryGlobalOverrideQuota(bytes
, quota::QuotaCallback());
106 // Don't return until the quota has been set.
107 scoped_refptr
<base::ThreadTestHelper
> helper(new base::ThreadTestHelper(
108 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB
)));
109 ASSERT_TRUE(helper
->Run());
112 virtual int64
RequestDiskUsage() {
113 PostTaskAndReplyWithResult(
114 GetContext()->TaskRunner(),
116 base::Bind(&IndexedDBContext::GetOriginDiskUsage
,
119 base::Bind(&IndexedDBBrowserTest::DidGetDiskUsage
, this));
120 scoped_refptr
<base::ThreadTestHelper
> helper(new base::ThreadTestHelper(
121 BrowserMainLoop::GetInstance()->indexed_db_thread()->
122 message_loop_proxy()));
123 EXPECT_TRUE(helper
->Run());
124 // Wait for DidGetDiskUsage to be called.
125 base::MessageLoop::current()->RunUntilIdle();
129 virtual void DidGetDiskUsage(int64 bytes
) {
137 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, CursorTest
) {
138 SimpleTest(GetTestUrl("indexeddb", "cursor_test.html"));
141 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, CursorTestIncognito
) {
142 SimpleTest(GetTestUrl("indexeddb", "cursor_test.html"),
143 true /* incognito */);
146 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, CursorPrefetch
) {
147 SimpleTest(GetTestUrl("indexeddb", "cursor_prefetch.html"));
150 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, IndexTest
) {
151 SimpleTest(GetTestUrl("indexeddb", "index_test.html"));
154 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, KeyPathTest
) {
155 SimpleTest(GetTestUrl("indexeddb", "key_path_test.html"));
158 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, TransactionGetTest
) {
159 SimpleTest(GetTestUrl("indexeddb", "transaction_get_test.html"));
162 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, KeyTypesTest
) {
163 SimpleTest(GetTestUrl("indexeddb", "key_types_test.html"));
166 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, ObjectStoreTest
) {
167 SimpleTest(GetTestUrl("indexeddb", "object_store_test.html"));
170 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, DatabaseTest
) {
171 SimpleTest(GetTestUrl("indexeddb", "database_test.html"));
174 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, TransactionTest
) {
175 SimpleTest(GetTestUrl("indexeddb", "transaction_test.html"));
178 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, CallbackAccounting
) {
179 SimpleTest(GetTestUrl("indexeddb", "callback_accounting.html"));
182 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, DoesntHangTest
) {
183 SimpleTest(GetTestUrl("indexeddb", "transaction_run_forever.html"));
184 CrashTab(shell()->web_contents());
185 SimpleTest(GetTestUrl("indexeddb", "transaction_not_blocked.html"));
188 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, Bug84933Test
) {
189 const GURL url
= GetTestUrl("indexeddb", "bug_84933.html");
191 // Just navigate to the URL. Test will crash if it fails.
192 NavigateToURLBlockUntilNavigationsComplete(shell(), url
, 1);
195 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, Bug106883Test
) {
196 const GURL url
= GetTestUrl("indexeddb", "bug_106883.html");
198 // Just navigate to the URL. Test will crash if it fails.
199 NavigateToURLBlockUntilNavigationsComplete(shell(), url
, 1);
202 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, Bug109187Test
) {
203 const GURL url
= GetTestUrl("indexeddb", "bug_109187.html");
205 // Just navigate to the URL. Test will crash if it fails.
206 NavigateToURLBlockUntilNavigationsComplete(shell(), url
, 1);
209 class IndexedDBBrowserTestWithLowQuota
: public IndexedDBBrowserTest
{
211 virtual void SetUpOnMainThread() OVERRIDE
{
212 const int kInitialQuotaKilobytes
= 5000;
213 SetQuota(kInitialQuotaKilobytes
);
217 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithLowQuota
, QuotaTest
) {
218 SimpleTest(GetTestUrl("indexeddb", "quota_test.html"));
221 class IndexedDBBrowserTestWithGCExposed
: public IndexedDBBrowserTest
{
223 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
224 command_line
->AppendSwitchASCII(switches::kJavaScriptFlags
, "--expose-gc");
228 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed
,
229 DatabaseCallbacksTest
) {
230 SimpleTest(GetTestUrl("indexeddb", "database_callbacks_first.html"));
233 static void CopyLevelDBToProfile(Shell
* shell
,
234 scoped_refptr
<IndexedDBContextImpl
> context
,
235 const std::string
& test_directory
) {
236 DCHECK(context
->TaskRunner()->RunsTasksOnCurrentThread());
237 base::FilePath
leveldb_dir(FILE_PATH_LITERAL("file__0.indexeddb.leveldb"));
238 base::FilePath test_data_dir
=
239 GetTestFilePath("indexeddb", test_directory
.c_str()).Append(leveldb_dir
);
240 base::FilePath dest
= context
->data_path().Append(leveldb_dir
);
241 // If we don't create the destination directory first, the contents of the
242 // leveldb directory are copied directly into profile/IndexedDB instead of
243 // profile/IndexedDB/file__0.xxx/
244 ASSERT_TRUE(base::CreateDirectory(dest
));
245 const bool kRecursive
= true;
246 ASSERT_TRUE(base::CopyDirectory(test_data_dir
,
247 context
->data_path(),
251 class IndexedDBBrowserTestWithPreexistingLevelDB
: public IndexedDBBrowserTest
{
253 virtual void SetUpOnMainThread() OVERRIDE
{
254 scoped_refptr
<IndexedDBContextImpl
> context
= GetContext();
255 context
->TaskRunner()->PostTask(
258 &CopyLevelDBToProfile
, shell(), context
, EnclosingLevelDBDir()));
259 scoped_refptr
<base::ThreadTestHelper
> helper(new base::ThreadTestHelper(
260 BrowserMainLoop::GetInstance()->indexed_db_thread()->
261 message_loop_proxy()));
262 ASSERT_TRUE(helper
->Run());
265 virtual std::string
EnclosingLevelDBDir() = 0;
269 class IndexedDBBrowserTestWithVersion0Schema
: public
270 IndexedDBBrowserTestWithPreexistingLevelDB
{
271 virtual std::string
EnclosingLevelDBDir() OVERRIDE
{
272 return "migration_from_0";
276 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion0Schema
, MigrationTest
) {
277 SimpleTest(GetTestUrl("indexeddb", "migration_test.html"));
280 class IndexedDBBrowserTestWithVersion123456Schema
: public
281 IndexedDBBrowserTestWithPreexistingLevelDB
{
282 virtual std::string
EnclosingLevelDBDir() OVERRIDE
{
283 return "schema_version_123456";
287 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion123456Schema
,
289 int64 original_size
= RequestDiskUsage();
290 EXPECT_GT(original_size
, 0);
291 SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
292 int64 new_size
= RequestDiskUsage();
293 EXPECT_NE(original_size
, new_size
);
296 class IndexedDBBrowserTestWithVersion987654SSVData
: public
297 IndexedDBBrowserTestWithPreexistingLevelDB
{
298 virtual std::string
EnclosingLevelDBDir() OVERRIDE
{
299 return "ssv_version_987654";
303 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion987654SSVData
,
305 int64 original_size
= RequestDiskUsage();
306 EXPECT_GT(original_size
, 0);
307 SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
308 int64 new_size
= RequestDiskUsage();
309 EXPECT_NE(original_size
, new_size
);
312 class IndexedDBBrowserTestWithCorruptLevelDB
: public
313 IndexedDBBrowserTestWithPreexistingLevelDB
{
314 virtual std::string
EnclosingLevelDBDir() OVERRIDE
{
315 return "corrupt_leveldb";
319 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithCorruptLevelDB
,
321 int64 original_size
= RequestDiskUsage();
322 EXPECT_GT(original_size
, 0);
323 SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
324 int64 new_size
= RequestDiskUsage();
325 EXPECT_NE(original_size
, new_size
);
328 class IndexedDBBrowserTestWithMissingSSTFile
: public
329 IndexedDBBrowserTestWithPreexistingLevelDB
{
330 virtual std::string
EnclosingLevelDBDir() OVERRIDE
{
331 return "missing_sst";
335 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithMissingSSTFile
,
337 int64 original_size
= RequestDiskUsage();
338 EXPECT_GT(original_size
, 0);
339 SimpleTest(GetTestUrl("indexeddb", "open_missing_table.html"));
340 int64 new_size
= RequestDiskUsage();
341 EXPECT_NE(original_size
, new_size
);
344 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, LevelDBLogFileTest
) {
345 // Any page that opens an IndexedDB will work here.
346 SimpleTest(GetTestUrl("indexeddb", "database_test.html"));
347 base::FilePath
leveldb_dir(FILE_PATH_LITERAL("file__0.indexeddb.leveldb"));
348 base::FilePath
log_file(FILE_PATH_LITERAL("LOG"));
349 base::FilePath log_file_path
=
350 GetContext()->data_path().Append(leveldb_dir
).Append(log_file
);
352 EXPECT_TRUE(base::GetFileSize(log_file_path
, &size
));
356 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, CanDeleteWhenOverQuotaTest
) {
357 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html"));
358 int64 size
= RequestDiskUsage();
359 const int kQuotaKilobytes
= 2;
360 EXPECT_GT(size
, kQuotaKilobytes
* 1024);
361 SetQuota(kQuotaKilobytes
);
362 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html"));
367 static void CompactIndexedDBBackingStore(
368 scoped_refptr
<IndexedDBContextImpl
> context
,
369 const GURL
& origin_url
) {
370 IndexedDBFactory
* factory
= context
->GetIDBFactory();
372 std::pair
<IndexedDBFactory::OriginDBMapIterator
,
373 IndexedDBFactory::OriginDBMapIterator
> range
=
374 factory
->GetOpenDatabasesForOrigin(origin_url
);
376 if (range
.first
== range
.second
) // If no open db's for this origin
379 // Compact the first db's backing store since all the db's are in the same
381 IndexedDBDatabase
* db
= range
.first
->second
;
382 IndexedDBBackingStore
* backing_store
= db
->backing_store();
383 backing_store
->Compact();
386 static void CorruptIndexedDBDatabase(
387 IndexedDBContextImpl
* context
,
388 const GURL
& origin_url
,
389 base::WaitableEvent
* signal_when_finished
) {
391 CompactIndexedDBBackingStore(context
, origin_url
);
395 base::FilePath idb_data_path
= context
->GetFilePath(origin_url
);
396 const bool recursive
= false;
397 base::FileEnumerator
enumerator(
398 idb_data_path
, recursive
, base::FileEnumerator::FILES
);
399 for (base::FilePath idb_file
= enumerator
.Next(); !idb_file
.empty();
400 idb_file
= enumerator
.Next()) {
402 GetFileSize(idb_file
, &size
);
404 if (idb_file
.Extension() == FILE_PATH_LITERAL(".ldb")) {
406 base::File
file(idb_file
,
407 base::File::FLAG_WRITE
| base::File::FLAG_OPEN_TRUNCATED
);
408 if (file
.IsValid()) {
409 // Was opened truncated, expand back to the original
410 // file size and fill with zeros (corrupting the file).
411 file
.SetLength(size
);
418 VLOG(0) << "There were " << numFiles
<< " in " << idb_data_path
.value()
419 << " with " << numErrors
<< " errors";
420 signal_when_finished
->Signal();
423 const std::string s_corrupt_db_test_prefix
= "/corrupt/test/";
425 static scoped_ptr
<net::test_server::HttpResponse
> CorruptDBRequestHandler(
426 IndexedDBContextImpl
* context
,
427 const GURL
& origin_url
,
428 const std::string
& path
,
429 const net::test_server::HttpRequest
& request
) {
431 std::string request_path
;
432 if (path
.find(s_corrupt_db_test_prefix
) != std::string::npos
)
433 request_path
= request
.relative_url
.substr(s_corrupt_db_test_prefix
.size());
435 return scoped_ptr
<net::test_server::HttpResponse
>();
437 // Remove the query string if present.
438 std::string request_query
;
439 size_t query_pos
= request_path
.find('?');
440 if (query_pos
!= std::string::npos
) {
441 request_query
= request_path
.substr(query_pos
+ 1);
442 request_path
= request_path
.substr(0, query_pos
);
445 if (request_path
== "corruptdb" && !request_query
.empty()) {
446 VLOG(0) << "Requested to corrupt IndexedDB: " << request_query
;
447 base::WaitableEvent
signal_when_finished(false, false);
448 context
->TaskRunner()->PostTask(FROM_HERE
,
449 base::Bind(&CorruptIndexedDBDatabase
,
450 base::ConstRef(context
),
452 &signal_when_finished
));
453 signal_when_finished
.Wait();
455 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
456 new net::test_server::BasicHttpResponse
);
457 http_response
->set_code(net::HTTP_OK
);
458 return http_response
.PassAs
<net::test_server::HttpResponse
>();
461 // A request for a test resource
462 base::FilePath resourcePath
=
463 content::GetTestFilePath("indexeddb", request_path
.c_str());
464 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
465 new net::test_server::BasicHttpResponse
);
466 http_response
->set_code(net::HTTP_OK
);
467 std::string file_contents
;
468 if (!base::ReadFileToString(resourcePath
, &file_contents
))
469 return scoped_ptr
<net::test_server::HttpResponse
>();
470 http_response
->set_content(file_contents
);
471 return http_response
.PassAs
<net::test_server::HttpResponse
>();
476 class IndexedDBBrowserCorruptionTest
477 : public IndexedDBBrowserTest
,
478 public ::testing::WithParamInterface
<const char*> {};
480 IN_PROC_BROWSER_TEST_P(IndexedDBBrowserCorruptionTest
,
481 OperationOnCorruptedOpenDatabase
) {
482 ASSERT_TRUE(embedded_test_server()->Started() ||
483 embedded_test_server()->InitializeAndWaitUntilReady());
484 const GURL
& origin_url
= embedded_test_server()->base_url();
485 embedded_test_server()->RegisterRequestHandler(
486 base::Bind(&CorruptDBRequestHandler
,
487 base::ConstRef(GetContext()),
489 s_corrupt_db_test_prefix
));
491 std::string test_file
= s_corrupt_db_test_prefix
+
492 "corrupted_open_db_detection.html#" + GetParam();
493 SimpleTest(embedded_test_server()->GetURL(test_file
));
495 test_file
= s_corrupt_db_test_prefix
+ "corrupted_open_db_recovery.html";
496 SimpleTest(embedded_test_server()->GetURL(test_file
));
499 INSTANTIATE_TEST_CASE_P(IndexedDBBrowserCorruptionTestInstantiation
,
500 IndexedDBBrowserCorruptionTest
,
501 ::testing::Values("get",
503 "clearObjectStore"));
505 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, DeleteCompactsBackingStore
) {
506 const GURL test_url
= GetTestUrl("indexeddb", "delete_compact.html");
507 SimpleTest(GURL(test_url
.spec() + "#fill"));
508 int64 after_filling
= RequestDiskUsage();
509 EXPECT_GT(after_filling
, 0);
511 SimpleTest(GURL(test_url
.spec() + "#purge"));
512 int64 after_deleting
= RequestDiskUsage();
513 EXPECT_LT(after_deleting
, after_filling
);
515 // The above tests verify basic assertions - that filling writes data and
516 // deleting reduces the amount stored.
518 // The below tests make assumptions about implementation specifics, such as
519 // data compression, compaction efficiency, and the maximum amount of
520 // metadata and log data remains after a deletion. It is possible that
521 // changes to the implementation may require these constants to be tweaked.
523 const int kTestFillBytes
= 1024 * 1024 * 5; // 5MB
524 EXPECT_GT(after_filling
, kTestFillBytes
);
526 const int kTestCompactBytes
= 1024 * 1024 * 1; // 1MB
527 EXPECT_LT(after_deleting
, kTestCompactBytes
);
530 // Complex multi-step (converted from pyauto) tests begin here.
532 // Verify null key path persists after restarting browser.
533 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, PRE_NullKeyPathPersistence
) {
534 NavigateAndWaitForTitle(shell(), "bug_90635.html", "#part1",
538 // Verify null key path persists after restarting browser.
539 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, NullKeyPathPersistence
) {
540 NavigateAndWaitForTitle(shell(), "bug_90635.html", "#part2",
541 "pass - second run");
544 // Verify that a VERSION_CHANGE transaction is rolled back after a
545 // renderer/browser crash
546 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
,
547 PRE_PRE_VersionChangeCrashResilience
) {
548 NavigateAndWaitForTitle(shell(), "version_change_crash.html", "#part1",
549 "pass - part1 - complete");
552 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, PRE_VersionChangeCrashResilience
) {
553 NavigateAndWaitForTitle(shell(), "version_change_crash.html", "#part2",
554 "pass - part2 - crash me");
555 NavigateToURL(shell(), GURL(kChromeUIBrowserCrashHost
));
558 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, VersionChangeCrashResilience
) {
559 NavigateAndWaitForTitle(shell(), "version_change_crash.html", "#part3",
560 "pass - part3 - rolled back");
563 // Verify that open DB connections are closed when a tab is destroyed.
564 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, ConnectionsClosedOnTabClose
) {
565 NavigateAndWaitForTitle(shell(), "version_change_blocked.html", "#tab1",
566 "setVersion(2) complete");
568 // Start on a different URL to force a new renderer process.
569 Shell
* new_shell
= CreateBrowser();
570 NavigateToURL(new_shell
, GURL(kAboutBlankURL
));
571 NavigateAndWaitForTitle(new_shell
, "version_change_blocked.html", "#tab2",
572 "setVersion(3) blocked");
574 base::string16
expected_title16(ASCIIToUTF16("setVersion(3) complete"));
575 TitleWatcher
title_watcher(new_shell
->web_contents(), expected_title16
);
578 shell()->web_contents()->GetRenderProcessHost()->GetHandle(), 0, true);
581 EXPECT_EQ(expected_title16
, title_watcher
.WaitAndGetTitle());
584 // Verify that a "close" event is fired at database connections when
585 // the backing store is deleted.
586 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest
, ForceCloseEventTest
) {
587 NavigateAndWaitForTitle(shell(), "force_close_event.html", NULL
,
590 GetContext()->TaskRunner()->PostTask(
592 base::Bind(&IndexedDBContextImpl::DeleteForOrigin
,
596 base::string16
expected_title16(ASCIIToUTF16("connection closed"));
597 TitleWatcher
title_watcher(shell()->web_contents(), expected_title16
);
598 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error"));
599 EXPECT_EQ(expected_title16
, title_watcher
.WaitAndGetTitle());
602 class IndexedDBBrowserTestSingleProcess
: public IndexedDBBrowserTest
{
604 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
605 command_line
->AppendSwitch(switches::kSingleProcess
);
609 // Crashing on Android due to kSingleProcess flag: http://crbug.com/342525
610 #if defined(OS_ANDROID)
611 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest
613 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest
615 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess
,
616 MAYBE_RenderThreadShutdownTest
) {
617 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html"));
620 } // namespace content