Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_enumerator.h" | |
| 8 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 9 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| 10 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 12 #include "base/test/thread_test_helper.h" | 13 #include "base/test/thread_test_helper.h" |
| 13 #include "content/browser/browser_main_loop.h" | 14 #include "content/browser/browser_main_loop.h" |
| 14 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 15 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 15 #include "content/browser/web_contents/web_contents_impl.h" | 16 #include "content/browser/web_contents/web_contents_impl.h" |
| 16 #include "content/public/browser/browser_context.h" | 17 #include "content/public/browser/browser_context.h" |
| 17 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/render_process_host.h" | 19 #include "content/public/browser/render_process_host.h" |
| 19 #include "content/public/browser/storage_partition.h" | 20 #include "content/public/browser/storage_partition.h" |
| 20 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
| 21 #include "content/public/common/content_switches.h" | 22 #include "content/public/common/content_switches.h" |
| 22 #include "content/public/common/url_constants.h" | 23 #include "content/public/common/url_constants.h" |
| 23 #include "content/public/test/browser_test_utils.h" | 24 #include "content/public/test/browser_test_utils.h" |
| 24 #include "content/shell/browser/shell.h" | 25 #include "content/shell/browser/shell.h" |
| 25 #include "content/test/content_browser_test.h" | 26 #include "content/test/content_browser_test.h" |
| 26 #include "content/test/content_browser_test_utils.h" | 27 #include "content/test/content_browser_test_utils.h" |
| 28 #include "net/base/net_errors.h" | |
| 29 #include "net/test/embedded_test_server/embedded_test_server.h" | |
| 30 #include "net/test/embedded_test_server/http_request.h" | |
| 31 #include "net/test/embedded_test_server/http_response.h" | |
| 27 #include "webkit/browser/database/database_util.h" | 32 #include "webkit/browser/database/database_util.h" |
| 28 #include "webkit/browser/quota/quota_manager.h" | 33 #include "webkit/browser/quota/quota_manager.h" |
| 29 | 34 |
| 30 using base::ASCIIToUTF16; | 35 using base::ASCIIToUTF16; |
| 31 using quota::QuotaManager; | 36 using quota::QuotaManager; |
| 32 using webkit_database::DatabaseUtil; | 37 using webkit_database::DatabaseUtil; |
| 33 | 38 |
| 34 namespace content { | 39 namespace content { |
| 35 | 40 |
| 36 // This browser test is aimed towards exercising the IndexedDB bindings and | 41 // This browser test is aimed towards exercising the IndexedDB bindings and |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 | 354 |
| 350 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) { | 355 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) { |
| 351 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html")); | 356 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html")); |
| 352 int64 size = RequestDiskUsage(); | 357 int64 size = RequestDiskUsage(); |
| 353 const int kQuotaKilobytes = 2; | 358 const int kQuotaKilobytes = 2; |
| 354 EXPECT_GT(size, kQuotaKilobytes * 1024); | 359 EXPECT_GT(size, kQuotaKilobytes * 1024); |
| 355 SetQuota(kQuotaKilobytes); | 360 SetQuota(kQuotaKilobytes); |
| 356 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html")); | 361 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html")); |
| 357 } | 362 } |
| 358 | 363 |
| 364 namespace { | |
| 365 | |
| 366 static void FlushIndexedDBDatabase(scoped_refptr<IndexedDBContextImpl> context, | |
|
jsbell
2014/03/26 18:16:58
'Database' or 'BackingStore' ?
cmumford
2014/03/26 21:40:36
Renamed to 'BackingStore'
| |
| 367 const GURL& origin_url) { | |
| 368 IndexedDBFactory* factory = context->GetIDBFactory(); | |
| 369 | |
| 370 std::pair<IndexedDBFactory::OriginDBMapIterator, | |
| 371 IndexedDBFactory::OriginDBMapIterator> range = | |
| 372 factory->GetOpenDatabasesForOrigin(origin_url); | |
| 373 | |
| 374 while (range.first != range.second) { | |
| 375 IndexedDBDatabase* db = range.first->second; | |
| 376 IndexedDBBackingStore* backing_store = db->backing_store(); | |
| 377 backing_store->Flush(); | |
|
jsbell
2014/03/26 18:16:58
All databases in an origin share a backing store,
cmumford
2014/03/26 21:40:36
Done.
| |
| 378 ++range.first; | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 static void CorruptIndexedDBDatabase( | |
|
jsbell
2014/03/26 18:16:58
Add comment about why it's async?
cmumford
2014/03/26 21:40:36
Actually it's effectively sync, but I didn't see a
jsbell
2014/03/26 22:49:00
Oops, yeah, I shouldn't have said "async". It wasn
| |
| 383 IndexedDBContextImpl* context, | |
| 384 const GURL& origin_url, | |
| 385 base::WaitableEvent* signal_when_finished) { | |
| 386 | |
| 387 FlushIndexedDBDatabase(context, origin_url); | |
| 388 | |
| 389 int numFiles = 0; | |
| 390 int numErrors = 0; | |
| 391 base::FilePath idb_data_path = context->GetFilePath(origin_url); | |
| 392 const bool recursive = false; | |
| 393 base::FileEnumerator enumerator( | |
| 394 idb_data_path, recursive, base::FileEnumerator::FILES); | |
| 395 for (base::FilePath idb_file = enumerator.Next(); !idb_file.empty(); | |
| 396 idb_file = enumerator.Next()) { | |
| 397 int64 size(0); | |
|
jsbell
2014/03/26 18:16:58
size_t?
cmumford
2014/03/26 21:40:36
Not according to base/file_util.h
jsbell
2014/03/26 22:49:00
Sorry. I swear I saw it as size_t. :(
| |
| 398 GetFileSize(idb_file, &size); | |
| 399 | |
| 400 if (idb_file.Extension() == ".ldb") { | |
| 401 numFiles++; | |
| 402 FILE* f = fopen(idb_file.value().c_str(), "w"); | |
|
jsbell
2014/03/26 18:16:58
Why FILE/fopen/fwrite instead of base::PlatformFil
cmumford
2014/03/26 21:40:36
I think I was unaware way back when I wrote this.
| |
| 403 if (f) { | |
| 404 char zero(0); | |
| 405 if (size != (int64)fwrite(&zero, sizeof(zero), size, f)) | |
| 406 numErrors++; | |
| 407 fclose(f); | |
| 408 } else { | |
| 409 numErrors++; | |
| 410 } | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 VLOG(0) << "There were " << numFiles << " in " << idb_data_path.value() | |
| 415 << " with " << numErrors << " errors"; | |
| 416 signal_when_finished->Signal(); | |
| 417 } | |
| 418 | |
| 419 const std::string s_corrupt_db_test_prefix = "/corrupt/test/"; | |
| 420 | |
| 421 static scoped_ptr<net::test_server::HttpResponse> CorruptDbRequestHandler( | |
|
jsbell
2014/03/26 18:16:58
Nit: Capitalize DB
cmumford
2014/03/26 21:40:36
Done.
| |
| 422 IndexedDBContextImpl* context, | |
| 423 const GURL& origin_url, | |
| 424 const std::string& path, | |
| 425 const net::test_server::HttpRequest& request) { | |
| 426 | |
| 427 std::string request_path; | |
| 428 if (path.find(s_corrupt_db_test_prefix) != std::string::npos) | |
| 429 request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size()); | |
| 430 else | |
| 431 return scoped_ptr<net::test_server::HttpResponse>(); | |
| 432 | |
| 433 // Remove the query string if present. | |
|
jsbell
2014/03/26 18:16:58
Can you use a GURL to make this parsing easier?
cmumford
2014/03/26 21:40:36
No, this is only the resource/query part of the UR
| |
| 434 std::string request_query; | |
| 435 size_t query_pos = request_path.find('?'); | |
| 436 if (query_pos != std::string::npos) { | |
| 437 request_query = request_path.substr(query_pos + 1); | |
| 438 request_path = request_path.substr(0, query_pos); | |
| 439 } | |
| 440 | |
| 441 if (request_path == "corruptdb" && !request_query.empty()) { | |
| 442 VLOG(0) << "Requested to currupt IndexedDB: " << request_query; | |
|
jsbell
2014/03/26 18:16:58
Typo: corrupt
cmumford
2014/03/26 21:40:36
Done.
| |
| 443 base::WaitableEvent signal_when_finished(false, false); | |
| 444 context->TaskRunner()->PostTask(FROM_HERE, | |
| 445 base::Bind(&CorruptIndexedDBDatabase, | |
| 446 base::ConstRef(context), | |
| 447 origin_url, | |
| 448 &signal_when_finished)); | |
| 449 signal_when_finished.Wait(); | |
| 450 | |
| 451 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | |
| 452 new net::test_server::BasicHttpResponse); | |
| 453 http_response->set_code(net::HTTP_OK); | |
| 454 return http_response.PassAs<net::test_server::HttpResponse>(); | |
| 455 } else { | |
|
jsbell
2014/03/26 18:16:58
No need for else block since if() early-exits.
cmumford
2014/03/26 21:40:36
Done.
| |
| 456 // A request for a test resource | |
|
jsbell
2014/03/26 18:16:58
Do we need to handle this? Can't the registered ha
cmumford
2014/03/26 21:40:36
From what I can tell this BasicHttpResponse object
jsbell
2014/03/26 22:49:00
Again, sorry - I thought the RegisterRequestHandle
| |
| 457 base::FilePath resourcePath = | |
| 458 content::GetTestFilePath("indexeddb", request_path.c_str()); | |
| 459 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | |
| 460 new net::test_server::BasicHttpResponse); | |
| 461 http_response->set_code(net::HTTP_OK); | |
| 462 std::string file_contents; | |
| 463 if (!base::ReadFileToString(resourcePath, &file_contents)) | |
| 464 return scoped_ptr<net::test_server::HttpResponse>(); | |
| 465 http_response->set_content(file_contents); | |
| 466 return http_response.PassAs<net::test_server::HttpResponse>(); | |
| 467 } | |
| 468 } | |
| 469 | |
| 470 } // namespace | |
| 471 | |
| 472 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CorruptedOpenDatabase) { | |
| 473 ASSERT_TRUE(embedded_test_server()->Started() || | |
| 474 embedded_test_server()->InitializeAndWaitUntilReady()); | |
| 475 const GURL& origin_url = embedded_test_server()->base_url(); | |
| 476 embedded_test_server()->RegisterRequestHandler( | |
| 477 base::Bind(&CorruptDbRequestHandler, | |
| 478 base::ConstRef(GetContext()), | |
| 479 origin_url, | |
| 480 s_corrupt_db_test_prefix)); | |
| 481 | |
| 482 std::string test_file = | |
| 483 s_corrupt_db_test_prefix + "corrupted_open_db_detection.html"; | |
| 484 SimpleTest(embedded_test_server()->GetURL(test_file)); | |
| 485 | |
| 486 test_file = s_corrupt_db_test_prefix + "corrupted_open_db_recovery.html"; | |
| 487 SimpleTest(embedded_test_server()->GetURL(test_file)); | |
| 488 } | |
| 489 | |
| 359 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) { | 490 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) { |
| 360 const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html"); | 491 const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html"); |
| 361 SimpleTest(GURL(test_url.spec() + "#fill")); | 492 SimpleTest(GURL(test_url.spec() + "#fill")); |
| 362 int64 after_filling = RequestDiskUsage(); | 493 int64 after_filling = RequestDiskUsage(); |
| 363 EXPECT_GT(after_filling, 0); | 494 EXPECT_GT(after_filling, 0); |
| 364 | 495 |
| 365 SimpleTest(GURL(test_url.spec() + "#purge")); | 496 SimpleTest(GURL(test_url.spec() + "#purge")); |
| 366 int64 after_deleting = RequestDiskUsage(); | 497 int64 after_deleting = RequestDiskUsage(); |
| 367 EXPECT_LT(after_deleting, after_filling); | 498 EXPECT_LT(after_deleting, after_filling); |
| 368 | 499 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 "connection ready"); | 573 "connection ready"); |
| 443 | 574 |
| 444 GetContext()->TaskRunner()->PostTask( | 575 GetContext()->TaskRunner()->PostTask( |
| 445 FROM_HERE, | 576 FROM_HERE, |
| 446 base::Bind(&IndexedDBContextImpl::DeleteForOrigin, | 577 base::Bind(&IndexedDBContextImpl::DeleteForOrigin, |
| 447 GetContext(), | 578 GetContext(), |
| 448 GURL("file:///"))); | 579 GURL("file:///"))); |
| 449 | 580 |
| 450 base::string16 expected_title16(ASCIIToUTF16("connection closed")); | 581 base::string16 expected_title16(ASCIIToUTF16("connection closed")); |
| 451 TitleWatcher title_watcher(shell()->web_contents(), expected_title16); | 582 TitleWatcher title_watcher(shell()->web_contents(), expected_title16); |
| 583 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error")); | |
| 452 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); | 584 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); |
| 453 } | 585 } |
| 454 | 586 |
| 455 class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest { | 587 class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest { |
| 456 public: | 588 public: |
| 457 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 589 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 458 command_line->AppendSwitch(switches::kSingleProcess); | 590 command_line->AppendSwitch(switches::kSingleProcess); |
| 459 } | 591 } |
| 460 }; | 592 }; |
| 461 | 593 |
| 462 // Crashing on Android due to kSingleProcess flag: http://crbug.com/342525 | 594 // Crashing on Android due to kSingleProcess flag: http://crbug.com/342525 |
| 463 #if defined(OS_ANDROID) | 595 #if defined(OS_ANDROID) |
| 464 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest | 596 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest |
| 465 #else | 597 #else |
| 466 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest | 598 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest |
| 467 #endif | 599 #endif |
| 468 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess, | 600 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess, |
| 469 MAYBE_RenderThreadShutdownTest) { | 601 MAYBE_RenderThreadShutdownTest) { |
| 470 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html")); | 602 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html")); |
| 471 } | 603 } |
| 472 | 604 |
| 473 } // namespace content | 605 } // namespace content |
| OLD | NEW |