Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: content/browser/indexed_db/indexed_db_browsertest.cc

Issue 1841553002: IndexedDB: Use url::Origin rather than GURL for representing origins (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@origin-idb
Patch Set: Rebased Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 26 matching lines...) Expand all
37 #include "content/public/test/content_browser_test_utils.h" 37 #include "content/public/test/content_browser_test_utils.h"
38 #include "content/shell/browser/shell.h" 38 #include "content/shell/browser/shell.h"
39 #include "net/base/escape.h" 39 #include "net/base/escape.h"
40 #include "net/base/net_errors.h" 40 #include "net/base/net_errors.h"
41 #include "net/test/embedded_test_server/embedded_test_server.h" 41 #include "net/test/embedded_test_server/embedded_test_server.h"
42 #include "net/test/embedded_test_server/http_request.h" 42 #include "net/test/embedded_test_server/http_request.h"
43 #include "net/test/embedded_test_server/http_response.h" 43 #include "net/test/embedded_test_server/http_response.h"
44 #include "storage/browser/blob/blob_storage_context.h" 44 #include "storage/browser/blob/blob_storage_context.h"
45 #include "storage/browser/database/database_util.h" 45 #include "storage/browser/database/database_util.h"
46 #include "storage/browser/quota/quota_manager.h" 46 #include "storage/browser/quota/quota_manager.h"
47 #include "url/gurl.h"
48 #include "url/origin.h"
47 49
48 using base::ASCIIToUTF16; 50 using base::ASCIIToUTF16;
49 using storage::QuotaManager; 51 using storage::QuotaManager;
50 using storage::DatabaseUtil; 52 using storage::DatabaseUtil;
53 using url::Origin;
51 54
52 namespace content { 55 namespace content {
53 56
54 // This browser test is aimed towards exercising the IndexedDB bindings and 57 // This browser test is aimed towards exercising the IndexedDB bindings and
55 // the actual implementation that lives in the browser side. 58 // the actual implementation that lives in the browser side.
56 class IndexedDBBrowserTest : public ContentBrowserTest, 59 class IndexedDBBrowserTest : public ContentBrowserTest,
57 public ::testing::WithParamInterface<const char*> { 60 public ::testing::WithParamInterface<const char*> {
58 public: 61 public:
59 IndexedDBBrowserTest() : disk_usage_(-1) {} 62 IndexedDBBrowserTest() : disk_usage_(-1) {}
60 63
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 EXPECT_TRUE(helper->Run()); 157 EXPECT_TRUE(helper->Run());
155 // Wait for DidGetDiskUsage to be called. 158 // Wait for DidGetDiskUsage to be called.
156 base::MessageLoop::current()->RunUntilIdle(); 159 base::MessageLoop::current()->RunUntilIdle();
157 return disk_usage_; 160 return disk_usage_;
158 } 161 }
159 162
160 virtual int RequestBlobFileCount() { 163 virtual int RequestBlobFileCount() {
161 PostTaskAndReplyWithResult( 164 PostTaskAndReplyWithResult(
162 GetContext()->TaskRunner(), FROM_HERE, 165 GetContext()->TaskRunner(), FROM_HERE,
163 base::Bind(&IndexedDBContextImpl::GetOriginBlobFileCount, GetContext(), 166 base::Bind(&IndexedDBContextImpl::GetOriginBlobFileCount, GetContext(),
164 GURL("file:///")), 167 Origin(GURL("file:///"))),
165 base::Bind(&IndexedDBBrowserTest::DidGetBlobFileCount, this)); 168 base::Bind(&IndexedDBBrowserTest::DidGetBlobFileCount, this));
166 scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper( 169 scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
167 BrowserMainLoop::GetInstance()->indexed_db_thread()->task_runner())); 170 BrowserMainLoop::GetInstance()->indexed_db_thread()->task_runner()));
168 EXPECT_TRUE(helper->Run()); 171 EXPECT_TRUE(helper->Run());
169 // Wait for DidGetBlobFileCount to be called. 172 // Wait for DidGetBlobFileCount to be called.
170 base::MessageLoop::current()->RunUntilIdle(); 173 base::MessageLoop::current()->RunUntilIdle();
171 return blob_file_count_; 174 return blob_file_count_;
172 } 175 }
173 176
174 private: 177 private:
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html")); 434 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html"));
432 int64_t size = RequestDiskUsage(); 435 int64_t size = RequestDiskUsage();
433 const int kQuotaKilobytes = 2; 436 const int kQuotaKilobytes = 2;
434 EXPECT_GT(size, kQuotaKilobytes * 1024); 437 EXPECT_GT(size, kQuotaKilobytes * 1024);
435 SetQuota(kQuotaKilobytes); 438 SetQuota(kQuotaKilobytes);
436 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html")); 439 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html"));
437 } 440 }
438 441
439 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) { 442 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) {
440 // First delete all IDB's for the test origin 443 // First delete all IDB's for the test origin
444 // TODO(jsbell): Remove static_cast<> when overloads are eliminated.
441 GetContext()->TaskRunner()->PostTask( 445 GetContext()->TaskRunner()->PostTask(
442 FROM_HERE, base::Bind(&IndexedDBContextImpl::DeleteForOrigin, 446 FROM_HERE,
443 GetContext(), GURL("file:///"))); 447 base::Bind(static_cast<void (IndexedDBContextImpl::*)(const GURL&)>(
448 &IndexedDBContextImpl::DeleteForOrigin),
449 GetContext(), GURL("file:///")));
444 EXPECT_EQ(0, RequestBlobFileCount()); // Start with no blob files. 450 EXPECT_EQ(0, RequestBlobFileCount()); // Start with no blob files.
445 const GURL test_url = GetTestUrl("indexeddb", "empty_blob.html"); 451 const GURL test_url = GetTestUrl("indexeddb", "empty_blob.html");
446 // For some reason Android's futimes fails (EPERM) in this test. Do not assert 452 // For some reason Android's futimes fails (EPERM) in this test. Do not assert
447 // file times on Android, but do so on other platforms. crbug.com/467247 453 // file times on Android, but do so on other platforms. crbug.com/467247
448 // TODO(cmumford): Figure out why this is the case and fix if possible. 454 // TODO(cmumford): Figure out why this is the case and fix if possible.
449 #if defined(OS_ANDROID) 455 #if defined(OS_ANDROID)
450 SimpleTest(GURL(test_url.spec() + "#ignoreTimes")); 456 SimpleTest(GURL(test_url.spec() + "#ignoreTimes"));
451 #else 457 #else
452 SimpleTest(GURL(test_url.spec())); 458 SimpleTest(GURL(test_url.spec()));
453 #endif 459 #endif
(...skipping 28 matching lines...) Expand all
482 488
483 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, BlobsCountAgainstQuota) { 489 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, BlobsCountAgainstQuota) {
484 SimpleTest(GetTestUrl("indexeddb", "blobs_use_quota.html")); 490 SimpleTest(GetTestUrl("indexeddb", "blobs_use_quota.html"));
485 } 491 }
486 492
487 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteForOriginDeletesBlobs) { 493 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteForOriginDeletesBlobs) {
488 SimpleTest(GetTestUrl("indexeddb", "write_20mb_blob.html")); 494 SimpleTest(GetTestUrl("indexeddb", "write_20mb_blob.html"));
489 int64_t size = RequestDiskUsage(); 495 int64_t size = RequestDiskUsage();
490 // This assertion assumes that we do not compress blobs. 496 // This assertion assumes that we do not compress blobs.
491 EXPECT_GT(size, 20 << 20 /* 20 MB */); 497 EXPECT_GT(size, 20 << 20 /* 20 MB */);
498 // TODO(jsbell): Remove static_cast<> when overloads are eliminated.
492 GetContext()->TaskRunner()->PostTask( 499 GetContext()->TaskRunner()->PostTask(
493 FROM_HERE, base::Bind(&IndexedDBContextImpl::DeleteForOrigin, 500 FROM_HERE,
494 GetContext(), GURL("file:///"))); 501 base::Bind(static_cast<void (IndexedDBContextImpl::*)(const GURL&)>(
502 &IndexedDBContextImpl::DeleteForOrigin),
503 GetContext(), GURL("file:///")));
495 scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper( 504 scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
496 BrowserMainLoop::GetInstance()->indexed_db_thread()->task_runner())); 505 BrowserMainLoop::GetInstance()->indexed_db_thread()->task_runner()));
497 ASSERT_TRUE(helper->Run()); 506 ASSERT_TRUE(helper->Run());
498 EXPECT_EQ(0, RequestDiskUsage()); 507 EXPECT_EQ(0, RequestDiskUsage());
499 } 508 }
500 509
501 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DiskFullOnCommit) { 510 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DiskFullOnCommit) {
502 // Ignore several preceding transactions: 511 // Ignore several preceding transactions:
503 // * The test calls deleteDatabase() which opens the backing store: 512 // * The test calls deleteDatabase() which opens the backing store:
504 // #1: IndexedDBBackingStore::OpenBackingStore 513 // #1: IndexedDBBackingStore::OpenBackingStore
(...skipping 11 matching lines...) Expand all
516 const int call_num = 1; 525 const int call_num = 1;
517 FailOperation(FAIL_CLASS_LEVELDB_TRANSACTION, FAIL_METHOD_COMMIT_DISK_FULL, 526 FailOperation(FAIL_CLASS_LEVELDB_TRANSACTION, FAIL_METHOD_COMMIT_DISK_FULL,
518 instance_num, call_num); 527 instance_num, call_num);
519 SimpleTest(GetTestUrl("indexeddb", "disk_full_on_commit.html")); 528 SimpleTest(GetTestUrl("indexeddb", "disk_full_on_commit.html"));
520 } 529 }
521 530
522 namespace { 531 namespace {
523 532
524 static void CompactIndexedDBBackingStore( 533 static void CompactIndexedDBBackingStore(
525 scoped_refptr<IndexedDBContextImpl> context, 534 scoped_refptr<IndexedDBContextImpl> context,
526 const GURL& origin_url) { 535 const Origin& origin) {
527 IndexedDBFactory* factory = context->GetIDBFactory(); 536 IndexedDBFactory* factory = context->GetIDBFactory();
528 537
529 std::pair<IndexedDBFactory::OriginDBMapIterator, 538 std::pair<IndexedDBFactory::OriginDBMapIterator,
530 IndexedDBFactory::OriginDBMapIterator> range = 539 IndexedDBFactory::OriginDBMapIterator>
531 factory->GetOpenDatabasesForOrigin(origin_url); 540 range = factory->GetOpenDatabasesForOrigin(origin);
532 541
533 if (range.first == range.second) // If no open db's for this origin 542 if (range.first == range.second) // If no open db's for this origin
534 return; 543 return;
535 544
536 // Compact the first db's backing store since all the db's are in the same 545 // Compact the first db's backing store since all the db's are in the same
537 // backing store. 546 // backing store.
538 IndexedDBDatabase* db = range.first->second; 547 IndexedDBDatabase* db = range.first->second;
539 IndexedDBBackingStore* backing_store = db->backing_store(); 548 IndexedDBBackingStore* backing_store = db->backing_store();
540 backing_store->Compact(); 549 backing_store->Compact();
541 } 550 }
542 551
543 static void CorruptIndexedDBDatabase( 552 static void CorruptIndexedDBDatabase(
544 IndexedDBContextImpl* context, 553 IndexedDBContextImpl* context,
545 const GURL& origin_url, 554 const Origin& origin,
546 base::WaitableEvent* signal_when_finished) { 555 base::WaitableEvent* signal_when_finished) {
547 556 CompactIndexedDBBackingStore(context, origin);
548 CompactIndexedDBBackingStore(context, origin_url);
549 557
550 int num_files = 0; 558 int num_files = 0;
551 int num_errors = 0; 559 int num_errors = 0;
552 const bool recursive = false; 560 const bool recursive = false;
553 for (const base::FilePath& idb_data_path : 561 for (const base::FilePath& idb_data_path : context->GetStoragePaths(origin)) {
554 context->GetStoragePaths(origin_url)) {
555 base::FileEnumerator enumerator( 562 base::FileEnumerator enumerator(
556 idb_data_path, recursive, base::FileEnumerator::FILES); 563 idb_data_path, recursive, base::FileEnumerator::FILES);
557 for (base::FilePath idb_file = enumerator.Next(); !idb_file.empty(); 564 for (base::FilePath idb_file = enumerator.Next(); !idb_file.empty();
558 idb_file = enumerator.Next()) { 565 idb_file = enumerator.Next()) {
559 int64_t size(0); 566 int64_t size(0);
560 GetFileSize(idb_file, &size); 567 GetFileSize(idb_file, &size);
561 568
562 if (idb_file.Extension() == FILE_PATH_LITERAL(".ldb")) { 569 if (idb_file.Extension() == FILE_PATH_LITERAL(".ldb")) {
563 num_files++; 570 num_files++;
564 base::File file( 571 base::File file(
(...skipping 11 matching lines...) Expand all
576 << " with " << num_errors << " errors"; 583 << " with " << num_errors << " errors";
577 } 584 }
578 585
579 signal_when_finished->Signal(); 586 signal_when_finished->Signal();
580 } 587 }
581 588
582 const std::string s_corrupt_db_test_prefix = "/corrupt/test/"; 589 const std::string s_corrupt_db_test_prefix = "/corrupt/test/";
583 590
584 static std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler( 591 static std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
585 IndexedDBContextImpl* context, 592 IndexedDBContextImpl* context,
586 const GURL& origin_url, 593 const Origin& origin,
587 const std::string& path, 594 const std::string& path,
588 IndexedDBBrowserTest* test, 595 IndexedDBBrowserTest* test,
589 const net::test_server::HttpRequest& request) { 596 const net::test_server::HttpRequest& request) {
590 std::string request_path; 597 std::string request_path;
591 if (path.find(s_corrupt_db_test_prefix) != std::string::npos) 598 if (path.find(s_corrupt_db_test_prefix) != std::string::npos)
592 request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size()); 599 request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size());
593 else 600 else
594 return std::unique_ptr<net::test_server::HttpResponse>(); 601 return std::unique_ptr<net::test_server::HttpResponse>();
595 602
596 // Remove the query string if present. 603 // Remove the query string if present.
597 std::string request_query; 604 std::string request_query;
598 size_t query_pos = request_path.find('?'); 605 size_t query_pos = request_path.find('?');
599 if (query_pos != std::string::npos) { 606 if (query_pos != std::string::npos) {
600 request_query = request_path.substr(query_pos + 1); 607 request_query = request_path.substr(query_pos + 1);
601 request_path = request_path.substr(0, query_pos); 608 request_path = request_path.substr(0, query_pos);
602 } 609 }
603 610
604 if (request_path == "corruptdb" && !request_query.empty()) { 611 if (request_path == "corruptdb" && !request_query.empty()) {
605 VLOG(0) << "Requested to corrupt IndexedDB: " << request_query; 612 VLOG(0) << "Requested to corrupt IndexedDB: " << request_query;
606 base::WaitableEvent signal_when_finished(false, false); 613 base::WaitableEvent signal_when_finished(false, false);
607 context->TaskRunner()->PostTask(FROM_HERE, 614 context->TaskRunner()->PostTask(
608 base::Bind(&CorruptIndexedDBDatabase, 615 FROM_HERE,
609 base::ConstRef(context), 616 base::Bind(&CorruptIndexedDBDatabase, base::ConstRef(context), origin,
610 origin_url, 617 &signal_when_finished));
611 &signal_when_finished));
612 signal_when_finished.Wait(); 618 signal_when_finished.Wait();
613 619
614 std::unique_ptr<net::test_server::BasicHttpResponse> http_response( 620 std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
615 new net::test_server::BasicHttpResponse); 621 new net::test_server::BasicHttpResponse);
616 http_response->set_code(net::HTTP_OK); 622 http_response->set_code(net::HTTP_OK);
617 return std::move(http_response); 623 return std::move(http_response);
618 } else if (request_path == "fail" && !request_query.empty()) { 624 } else if (request_path == "fail" && !request_query.empty()) {
619 FailClass failure_class = FAIL_CLASS_NOTHING; 625 FailClass failure_class = FAIL_CLASS_NOTHING;
620 FailMethod failure_method = FAIL_METHOD_NOTHING; 626 FailMethod failure_method = FAIL_METHOD_NOTHING;
621 int instance_num = 1; 627 int instance_num = 1;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 return std::unique_ptr<net::test_server::HttpResponse>(); 700 return std::unique_ptr<net::test_server::HttpResponse>();
695 http_response->set_content(file_contents); 701 http_response->set_content(file_contents);
696 return std::move(http_response); 702 return std::move(http_response);
697 } 703 }
698 704
699 } // namespace 705 } // namespace
700 706
701 IN_PROC_BROWSER_TEST_P(IndexedDBBrowserTest, OperationOnCorruptedOpenDatabase) { 707 IN_PROC_BROWSER_TEST_P(IndexedDBBrowserTest, OperationOnCorruptedOpenDatabase) {
702 ASSERT_TRUE(embedded_test_server()->Started() || 708 ASSERT_TRUE(embedded_test_server()->Started() ||
703 embedded_test_server()->Start()); 709 embedded_test_server()->Start());
704 const GURL& origin_url = embedded_test_server()->base_url(); 710 const Origin origin(embedded_test_server()->base_url());
705 embedded_test_server()->RegisterRequestHandler( 711 embedded_test_server()->RegisterRequestHandler(
706 base::Bind(&CorruptDBRequestHandler, 712 base::Bind(&CorruptDBRequestHandler, base::Unretained(GetContext()),
707 base::Unretained(GetContext()), 713 origin, s_corrupt_db_test_prefix, this));
708 origin_url,
709 s_corrupt_db_test_prefix,
710 this));
711 714
712 std::string test_file = s_corrupt_db_test_prefix + 715 std::string test_file = s_corrupt_db_test_prefix +
713 "corrupted_open_db_detection.html#" + GetParam(); 716 "corrupted_open_db_detection.html#" + GetParam();
714 SimpleTest(embedded_test_server()->GetURL(test_file)); 717 SimpleTest(embedded_test_server()->GetURL(test_file));
715 718
716 test_file = s_corrupt_db_test_prefix + "corrupted_open_db_recovery.html"; 719 test_file = s_corrupt_db_test_prefix + "corrupted_open_db_recovery.html";
717 SimpleTest(embedded_test_server()->GetURL(test_file)); 720 SimpleTest(embedded_test_server()->GetURL(test_file));
718 } 721 }
719 722
720 INSTANTIATE_TEST_CASE_P(IndexedDBBrowserTestInstantiation, 723 INSTANTIATE_TEST_CASE_P(IndexedDBBrowserTestInstantiation,
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 shell()->Close(); 827 shell()->Close();
825 828
826 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); 829 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
827 } 830 }
828 831
829 // Verify that a "close" event is fired at database connections when 832 // Verify that a "close" event is fired at database connections when
830 // the backing store is deleted. 833 // the backing store is deleted.
831 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) { 834 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) {
832 NavigateAndWaitForTitle(shell(), "force_close_event.html", NULL, 835 NavigateAndWaitForTitle(shell(), "force_close_event.html", NULL,
833 "connection ready"); 836 "connection ready");
834 837 // TODO(jsbell): Remove static_cast<> when overloads are eliminated.
835 GetContext()->TaskRunner()->PostTask( 838 GetContext()->TaskRunner()->PostTask(
836 FROM_HERE, 839 FROM_HERE,
837 base::Bind(&IndexedDBContextImpl::DeleteForOrigin, 840 base::Bind(static_cast<void (IndexedDBContextImpl::*)(const GURL&)>(
838 GetContext(), 841 &IndexedDBContextImpl::DeleteForOrigin),
839 GURL("file:///"))); 842 GetContext(), GURL("file:///")));
840 843
841 base::string16 expected_title16(ASCIIToUTF16("connection closed")); 844 base::string16 expected_title16(ASCIIToUTF16("connection closed"));
842 TitleWatcher title_watcher(shell()->web_contents(), expected_title16); 845 TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
843 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error")); 846 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error"));
844 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); 847 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
845 } 848 }
846 849
847 class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest { 850 class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest {
848 public: 851 public:
849 void SetUpCommandLine(base::CommandLine* command_line) override { 852 void SetUpCommandLine(base::CommandLine* command_line) override {
850 command_line->AppendSwitch(switches::kSingleProcess); 853 command_line->AppendSwitch(switches::kSingleProcess);
851 } 854 }
852 }; 855 };
853 856
854 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess, 857 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess,
855 RenderThreadShutdownTest) { 858 RenderThreadShutdownTest) {
856 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html")); 859 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html"));
857 } 860 }
858 861
859 } // namespace content 862 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_backing_store_unittest.cc ('k') | content/browser/indexed_db/indexed_db_callbacks.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698