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.h" | 8 #include "base/files/file.h" |
| 9 #include "base/files/file_enumerator.h" | 9 #include "base/files/file_enumerator.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/lazy_instance.h" | |
| 11 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/strings/string_split.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/test/thread_test_helper.h" | 16 #include "base/test/thread_test_helper.h" |
| 15 #include "content/browser/browser_main_loop.h" | 17 #include "content/browser/browser_main_loop.h" |
| 18 #include "content/browser/indexed_db/indexed_db_class_factory.h" | |
| 16 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 19 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 17 #include "content/browser/web_contents/web_contents_impl.h" | 20 #include "content/browser/web_contents/web_contents_impl.h" |
| 18 #include "content/public/browser/browser_context.h" | 21 #include "content/public/browser/browser_context.h" |
| 19 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/render_process_host.h" | 23 #include "content/public/browser/render_process_host.h" |
| 21 #include "content/public/browser/storage_partition.h" | 24 #include "content/public/browser/storage_partition.h" |
| 22 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
| 23 #include "content/public/common/content_switches.h" | 26 #include "content/public/common/content_switches.h" |
| 24 #include "content/public/common/url_constants.h" | 27 #include "content/public/common/url_constants.h" |
| 25 #include "content/public/test/browser_test_utils.h" | 28 #include "content/public/test/browser_test_utils.h" |
| 26 #include "content/public/test/content_browser_test.h" | 29 #include "content/public/test/content_browser_test.h" |
| 27 #include "content/public/test/content_browser_test_utils.h" | 30 #include "content/public/test/content_browser_test_utils.h" |
| 28 #include "content/shell/browser/shell.h" | 31 #include "content/shell/browser/shell.h" |
| 29 #include "net/base/net_errors.h" | 32 #include "net/base/net_errors.h" |
| 30 #include "net/test/embedded_test_server/embedded_test_server.h" | 33 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 31 #include "net/test/embedded_test_server/http_request.h" | 34 #include "net/test/embedded_test_server/http_request.h" |
| 32 #include "net/test/embedded_test_server/http_response.h" | 35 #include "net/test/embedded_test_server/http_response.h" |
| 33 #include "webkit/browser/database/database_util.h" | 36 #include "webkit/browser/database/database_util.h" |
| 34 #include "webkit/browser/quota/quota_manager.h" | 37 #include "webkit/browser/quota/quota_manager.h" |
| 35 | 38 |
| 36 using base::ASCIIToUTF16; | 39 using base::ASCIIToUTF16; |
| 37 using quota::QuotaManager; | 40 using quota::QuotaManager; |
| 38 using webkit_database::DatabaseUtil; | 41 using webkit_database::DatabaseUtil; |
| 39 | 42 |
| 40 namespace content { | 43 namespace content { |
| 41 | 44 |
| 45 enum FailClass { | |
| 46 FAIL_CLASS_NOTHING, | |
| 47 FAIL_CLASS_LEVELDB_TRANSACTION, | |
| 48 }; | |
| 49 | |
| 50 enum FailMethod { | |
| 51 FAIL_METHOD_NOTHING, | |
| 52 FAIL_METHOD_COMMIT, | |
| 53 FAIL_METHOD_GET, | |
| 54 }; | |
| 55 | |
| 56 class FunctionTracer { | |
| 57 public: | |
| 58 FunctionTracer(const std::string& class_name, | |
| 59 const std::string& method_name, | |
| 60 int instance_num) | |
| 61 : class_name_(class_name), | |
| 62 method_name_(method_name), | |
| 63 instance_count_(instance_num), | |
| 64 current_call_num_(0) {} | |
| 65 | |
| 66 void log_call() { | |
| 67 current_call_num_++; | |
| 68 VLOG(0) << class_name_ << '[' << instance_count_ << "]::" << method_name_ | |
| 69 << "()[" << current_call_num_ << ']'; | |
| 70 } | |
| 71 | |
| 72 private: | |
| 73 std::string class_name_; | |
| 74 std::string method_name_; | |
| 75 int instance_count_; | |
| 76 int current_call_num_; | |
| 77 }; | |
| 78 | |
| 79 class LevelDBTestTansaction : public LevelDBTransaction { | |
| 80 public: | |
| 81 LevelDBTestTansaction(LevelDBDatabase* db, | |
| 82 FailMethod fail_method, | |
| 83 int fail_on_call_num) | |
| 84 : LevelDBTransaction(db), | |
| 85 fail_method_(fail_method), | |
| 86 fail_on_call_num_(fail_on_call_num), | |
| 87 current_call_num_(0) { | |
| 88 DCHECK(fail_method != FAIL_METHOD_NOTHING); | |
| 89 DCHECK_GT(fail_on_call_num, 0); | |
| 90 } | |
| 91 | |
| 92 virtual leveldb::Status Get(const base::StringPiece& key, | |
| 93 std::string* value, | |
| 94 bool* found) OVERRIDE { | |
| 95 if (fail_method_ != FAIL_METHOD_GET || | |
| 96 ++current_call_num_ != fail_on_call_num_) | |
| 97 return LevelDBTransaction::Get(key, value, found); | |
| 98 | |
| 99 *found = false; | |
| 100 return leveldb::Status::Corruption("Corrupted for the test"); | |
| 101 } | |
| 102 | |
| 103 virtual leveldb::Status Commit() OVERRIDE { | |
| 104 if (fail_method_ != FAIL_METHOD_COMMIT || | |
| 105 ++current_call_num_ != fail_on_call_num_) | |
| 106 return LevelDBTransaction::Commit(); | |
| 107 | |
| 108 return leveldb::Status::Corruption("Corrupted for the test"); | |
| 109 } | |
| 110 | |
| 111 private: | |
| 112 virtual ~LevelDBTestTansaction() {} | |
| 113 | |
| 114 FailMethod fail_method_; | |
| 115 int fail_on_call_num_; | |
| 116 int current_call_num_; | |
| 117 }; | |
| 118 | |
| 119 class LevelDBTraceTansaction : public LevelDBTransaction { | |
| 120 public: | |
| 121 LevelDBTraceTansaction(LevelDBDatabase* db, int tx_num) | |
| 122 : LevelDBTransaction(db), | |
| 123 commit_tracer_(s_class_name, "Commit", tx_num), | |
| 124 get_tracer_(s_class_name, "Get", tx_num) {} | |
| 125 | |
| 126 virtual leveldb::Status Get(const base::StringPiece& key, | |
| 127 std::string* value, | |
| 128 bool* found) OVERRIDE { | |
| 129 get_tracer_.log_call(); | |
| 130 return LevelDBTransaction::Get(key, value, found); | |
| 131 } | |
| 132 | |
| 133 virtual leveldb::Status Commit() OVERRIDE { | |
| 134 commit_tracer_.log_call(); | |
| 135 return LevelDBTransaction::Commit(); | |
| 136 } | |
| 137 | |
| 138 private: | |
| 139 virtual ~LevelDBTraceTansaction() {} | |
| 140 | |
| 141 const std::string s_class_name = "LevelDBTransaction"; | |
| 142 | |
| 143 FunctionTracer commit_tracer_; | |
| 144 FunctionTracer get_tracer_; | |
| 145 }; | |
| 146 | |
| 147 class IndexedDBBrowserTestClassFactory : public IndexedDBClassFactory { | |
| 148 public: | |
| 149 IndexedDBBrowserTestClassFactory() | |
| 150 : failure_class_(FAIL_CLASS_NOTHING), | |
| 151 failure_method_(FAIL_METHOD_NOTHING), | |
| 152 only_trace_calls_(false) {} | |
| 153 virtual LevelDBTransaction* CreateLevelDBTransaction( | |
| 154 LevelDBDatabase* db) OVERRIDE { | |
| 155 instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION] = | |
| 156 instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION] + 1; | |
| 157 if (only_trace_calls_) { | |
| 158 return new LevelDBTraceTansaction( | |
| 159 db, instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION]); | |
| 160 } else { | |
| 161 if (failure_class_ == FAIL_CLASS_LEVELDB_TRANSACTION && | |
| 162 instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION] == | |
| 163 fail_on_instance_num_[FAIL_CLASS_LEVELDB_TRANSACTION]) | |
| 164 return new LevelDBTestTansaction( | |
| 165 db, | |
| 166 failure_method_, | |
| 167 fail_on_call_num_[FAIL_CLASS_LEVELDB_TRANSACTION]); | |
| 168 else | |
| 169 return IndexedDBClassFactory::CreateLevelDBTransaction(db); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 void FailOperation(FailClass failure_class, | |
| 174 FailMethod failure_method, | |
| 175 int fail_on_instance_num, | |
| 176 int fail_on_call_num) { | |
| 177 VLOG(0) << "FailOperation: class=" << failure_class | |
| 178 << ", method=" << failure_method | |
| 179 << ", instanceNum=" << fail_on_instance_num | |
| 180 << ", callNum=" << fail_on_call_num; | |
| 181 DCHECK(failure_class != FAIL_CLASS_NOTHING); | |
| 182 DCHECK(failure_method != FAIL_METHOD_NOTHING); | |
| 183 failure_class_ = failure_class; | |
| 184 failure_method_ = failure_method; | |
| 185 fail_on_instance_num_[failure_class_] = fail_on_instance_num; | |
| 186 fail_on_call_num_[failure_class_] = fail_on_call_num; | |
| 187 instance_count_.clear(); | |
| 188 } | |
| 189 | |
| 190 void Reset() { | |
| 191 failure_method_ = FAIL_METHOD_NOTHING; | |
| 192 instance_count_.clear(); | |
| 193 fail_on_instance_num_.clear(); | |
| 194 fail_on_call_num_.clear(); | |
| 195 } | |
| 196 | |
| 197 private: | |
| 198 FailClass failure_class_; | |
| 199 FailMethod failure_method_; | |
| 200 std::map<FailClass, int> instance_count_; | |
| 201 std::map<FailClass, int> fail_on_instance_num_; | |
| 202 std::map<FailClass, int> fail_on_call_num_; | |
| 203 bool only_trace_calls_; | |
| 204 }; | |
| 205 | |
| 206 static ::base::LazyInstance<IndexedDBBrowserTestClassFactory>::Leaky s_factory = | |
| 207 LAZY_INSTANCE_INITIALIZER; | |
| 208 | |
| 42 // This browser test is aimed towards exercising the IndexedDB bindings and | 209 // This browser test is aimed towards exercising the IndexedDB bindings and |
| 43 // the actual implementation that lives in the browser side. | 210 // the actual implementation that lives in the browser side. |
| 44 class IndexedDBBrowserTest : public ContentBrowserTest { | 211 class IndexedDBBrowserTest : public ContentBrowserTest { |
| 45 public: | 212 public: |
| 46 IndexedDBBrowserTest() : disk_usage_(-1) {} | 213 IndexedDBBrowserTest() |
| 214 : disk_usage_(-1), | |
| 215 test_class_factory_(new IndexedDBBrowserTestClassFactory) {} | |
|
ericu
2014/06/17 01:12:53
Is test_class_factory_ actually used somewhere? I
cmumford
2014/06/17 16:29:24
Embarrassingly no :-|
| |
| 216 | |
| 217 static IndexedDBClassFactory* GetIDBClassFactory() { | |
| 218 return s_factory.Pointer(); | |
| 219 } | |
| 220 | |
| 221 virtual void SetUp() OVERRIDE { | |
| 222 s_factory.Get().Reset(); | |
| 223 IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(GetIDBClassFactory); | |
| 224 ContentBrowserTest::SetUp(); | |
| 225 } | |
| 226 | |
| 227 virtual void TearDown() OVERRIDE { | |
| 228 IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(NULL); | |
|
ericu
2014/06/17 01:12:53
Given this cleanup, do we need s_factory to be a s
cmumford
2014/06/17 16:29:24
I was able to eliminate the use of s_factory in Co
| |
| 229 ContentBrowserTest::TearDown(); | |
| 230 } | |
| 47 | 231 |
| 48 void SimpleTest(const GURL& test_url, bool incognito = false) { | 232 void SimpleTest(const GURL& test_url, bool incognito = false) { |
| 49 // The test page will perform tests on IndexedDB, then navigate to either | 233 // The test page will perform tests on IndexedDB, then navigate to either |
| 50 // a #pass or #fail ref. | 234 // a #pass or #fail ref. |
| 51 Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell(); | 235 Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell(); |
| 52 | 236 |
| 53 VLOG(0) << "Navigating to URL and blocking."; | 237 VLOG(0) << "Navigating to URL and blocking."; |
| 54 NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2); | 238 NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2); |
| 55 VLOG(0) << "Navigation done."; | 239 VLOG(0) << "Navigation done."; |
| 56 std::string result = | 240 std::string result = |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 return disk_usage_; | 310 return disk_usage_; |
| 127 } | 311 } |
| 128 | 312 |
| 129 private: | 313 private: |
| 130 virtual void DidGetDiskUsage(int64 bytes) { | 314 virtual void DidGetDiskUsage(int64 bytes) { |
| 131 EXPECT_GT(bytes, 0); | 315 EXPECT_GT(bytes, 0); |
| 132 disk_usage_ = bytes; | 316 disk_usage_ = bytes; |
| 133 } | 317 } |
| 134 | 318 |
| 135 int64 disk_usage_; | 319 int64 disk_usage_; |
| 320 IndexedDBBrowserTestClassFactory* test_class_factory_; | |
| 136 | 321 |
| 137 DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTest); | 322 DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTest); |
| 138 }; | 323 }; |
| 139 | 324 |
| 140 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) { | 325 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) { |
| 141 SimpleTest(GetTestUrl("indexeddb", "cursor_test.html")); | 326 SimpleTest(GetTestUrl("indexeddb", "cursor_test.html")); |
| 142 } | 327 } |
| 143 | 328 |
| 144 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) { | 329 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) { |
| 145 SimpleTest(GetTestUrl("indexeddb", "cursor_test.html"), | 330 SimpleTest(GetTestUrl("indexeddb", "cursor_test.html"), |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 const net::test_server::HttpRequest& request) { | 630 const net::test_server::HttpRequest& request) { |
| 446 | 631 |
| 447 std::string request_path; | 632 std::string request_path; |
| 448 if (path.find(s_corrupt_db_test_prefix) != std::string::npos) | 633 if (path.find(s_corrupt_db_test_prefix) != std::string::npos) |
| 449 request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size()); | 634 request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size()); |
| 450 else | 635 else |
| 451 return scoped_ptr<net::test_server::HttpResponse>(); | 636 return scoped_ptr<net::test_server::HttpResponse>(); |
| 452 | 637 |
| 453 // Remove the query string if present. | 638 // Remove the query string if present. |
| 454 std::string request_query; | 639 std::string request_query; |
| 640 std::vector<std::pair<std::string, std::string> > query_params; | |
| 455 size_t query_pos = request_path.find('?'); | 641 size_t query_pos = request_path.find('?'); |
| 456 if (query_pos != std::string::npos) { | 642 if (query_pos != std::string::npos) { |
| 457 request_query = request_path.substr(query_pos + 1); | 643 request_query = request_path.substr(query_pos + 1); |
| 458 request_path = request_path.substr(0, query_pos); | 644 request_path = request_path.substr(0, query_pos); |
| 645 | |
| 646 base::SplitStringIntoKeyValuePairs(request_query, '=', '&', &query_params); | |
| 459 } | 647 } |
| 460 | 648 |
| 461 if (request_path == "corruptdb" && !request_query.empty()) { | 649 if (request_path == "corruptdb" && !request_query.empty()) { |
| 462 VLOG(0) << "Requested to corrupt IndexedDB: " << request_query; | 650 VLOG(0) << "Requested to corrupt IndexedDB: " << request_query; |
| 463 base::WaitableEvent signal_when_finished(false, false); | 651 base::WaitableEvent signal_when_finished(false, false); |
| 464 context->TaskRunner()->PostTask(FROM_HERE, | 652 context->TaskRunner()->PostTask(FROM_HERE, |
| 465 base::Bind(&CorruptIndexedDBDatabase, | 653 base::Bind(&CorruptIndexedDBDatabase, |
| 466 base::ConstRef(context), | 654 base::ConstRef(context), |
| 467 origin_url, | 655 origin_url, |
| 468 &signal_when_finished)); | 656 &signal_when_finished)); |
| 469 signal_when_finished.Wait(); | 657 signal_when_finished.Wait(); |
| 470 | 658 |
| 471 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | 659 scoped_ptr<net::test_server::BasicHttpResponse> http_response( |
| 472 new net::test_server::BasicHttpResponse); | 660 new net::test_server::BasicHttpResponse); |
| 473 http_response->set_code(net::HTTP_OK); | 661 http_response->set_code(net::HTTP_OK); |
| 474 return http_response.PassAs<net::test_server::HttpResponse>(); | 662 return http_response.PassAs<net::test_server::HttpResponse>(); |
| 663 } else if (request_path == "fail" && !query_params.empty()) { | |
| 664 FailClass failure_class = FAIL_CLASS_NOTHING; | |
| 665 FailMethod failure_method = FAIL_METHOD_NOTHING; | |
| 666 int instance_num = 1; | |
| 667 int call_num = 1; | |
| 668 std::string fail_class; | |
| 669 std::string fail_method; | |
| 670 | |
| 671 for (std::vector<std::pair<std::string, std::string> >::iterator it = | |
| 672 query_params.begin(); | |
| 673 it != query_params.end(); | |
| 674 it++) { | |
| 675 if (it->first == "method") | |
| 676 fail_method = it->second; | |
| 677 else if (it->first == "class") | |
| 678 fail_class = it->second; | |
| 679 else if (it->first == "num") | |
|
ericu
2014/06/17 01:12:53
Should "num" be qualified, just as "callNum" is?
cmumford
2014/06/17 16:29:24
How about "instNum"?
ericu
2014/06/17 17:03:04
Sure.
| |
| 680 instance_num = atoi(it->second.c_str()); | |
| 681 else if (it->first == "callNum") | |
| 682 call_num = atoi(it->second.c_str()); | |
| 683 else { | |
| 684 VLOG(0) << "Unknown param: \"" << it->first << '"'; | |
| 685 NOTREACHED(); | |
| 686 } | |
| 687 } | |
| 688 | |
| 689 if (fail_class == "LevelDBTransaction") { | |
| 690 failure_class = FAIL_CLASS_LEVELDB_TRANSACTION; | |
| 691 if (fail_method == "Get") | |
| 692 failure_method = FAIL_METHOD_GET; | |
| 693 else if (fail_method == "Commit") | |
| 694 failure_method = FAIL_METHOD_COMMIT; | |
| 695 } | |
|
ericu
2014/06/17 01:12:53
else...? It's undoubtedly a typo of some sort.
cmumford
2014/06/17 16:29:24
Done. A DCHECK would have caught the error, but a
| |
| 696 | |
| 697 DCHECK(instance_num >= 1); | |
| 698 DCHECK(call_num >= 1); | |
| 699 | |
| 700 s_factory.Get().FailOperation( | |
| 701 failure_class, failure_method, instance_num, call_num); | |
| 702 | |
| 703 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | |
| 704 new net::test_server::BasicHttpResponse); | |
| 705 http_response->set_code(net::HTTP_OK); | |
| 706 return http_response.PassAs<net::test_server::HttpResponse>(); | |
| 707 } else if (request_path == "nothing") { | |
|
ericu
2014/06/17 01:12:53
Is this clause needed by anything, or do you have
cmumford
2014/06/17 16:29:24
Oops - shouldn't have been there. I was experiment
| |
| 708 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | |
| 709 new net::test_server::BasicHttpResponse); | |
| 710 http_response->set_code(net::HTTP_OK); | |
| 711 return http_response.PassAs<net::test_server::HttpResponse>(); | |
| 475 } | 712 } |
| 476 | 713 |
| 477 // A request for a test resource | 714 // A request for a test resource |
| 478 base::FilePath resourcePath = | 715 base::FilePath resourcePath = |
| 479 content::GetTestFilePath("indexeddb", request_path.c_str()); | 716 content::GetTestFilePath("indexeddb", request_path.c_str()); |
| 480 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | 717 scoped_ptr<net::test_server::BasicHttpResponse> http_response( |
| 481 new net::test_server::BasicHttpResponse); | 718 new net::test_server::BasicHttpResponse); |
| 482 http_response->set_code(net::HTTP_OK); | 719 http_response->set_code(net::HTTP_OK); |
| 483 std::string file_contents; | 720 std::string file_contents; |
| 484 if (!base::ReadFileToString(resourcePath, &file_contents)) | 721 if (!base::ReadFileToString(resourcePath, &file_contents)) |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 629 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest | 866 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest |
| 630 #else | 867 #else |
| 631 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest | 868 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest |
| 632 #endif | 869 #endif |
| 633 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess, | 870 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess, |
| 634 MAYBE_RenderThreadShutdownTest) { | 871 MAYBE_RenderThreadShutdownTest) { |
| 635 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html")); | 872 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html")); |
| 636 } | 873 } |
| 637 | 874 |
| 638 } // namespace content | 875 } // namespace content |
| OLD | NEW |