| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/download_manager.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/public/test/test_utils.h" |
| #include "content/shell/browser/shell.h" |
| #include "content/test/net/url_request_mock_http_job.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| |
| class DatabaseTest : public ContentBrowserTest { |
| public: |
| DatabaseTest() {} |
| |
| void RunScriptAndCheckResult(Shell* shell, |
| const std::string& script, |
| const std::string& result) { |
| std::string data; |
| ASSERT_TRUE(ExecuteScriptAndExtractString( |
| shell->web_contents(), |
| script, |
| &data)); |
| ASSERT_EQ(data, result); |
| } |
| |
| void Navigate(Shell* shell) { |
| NavigateToURL(shell, GetTestUrl("", "simple_database.html")); |
| } |
| |
| void CreateTable(Shell* shell) { |
| RunScriptAndCheckResult(shell, "createTable()", "done"); |
| } |
| |
| void InsertRecord(Shell* shell, const std::string& data) { |
| RunScriptAndCheckResult(shell, "insertRecord('" + data + "')", "done"); |
| } |
| |
| void UpdateRecord(Shell* shell, int index, const std::string& data) { |
| RunScriptAndCheckResult( |
| shell, |
| "updateRecord(" + base::IntToString(index) + ", '" + data + "')", |
| "done"); |
| } |
| |
| void DeleteRecord(Shell* shell, int index) { |
| RunScriptAndCheckResult( |
| shell, "deleteRecord(" + base::IntToString(index) + ")", "done"); |
| } |
| |
| void CompareRecords(Shell* shell, const std::string& expected) { |
| RunScriptAndCheckResult(shell, "getRecords()", expected); |
| } |
| |
| bool HasTable(Shell* shell) { |
| std::string data; |
| CHECK(ExecuteScriptAndExtractString( |
| shell->web_contents(), |
| "getRecords()", |
| &data)); |
| return data != "getRecords error: [object SQLError]"; |
| } |
| }; |
| |
| // Insert records to the database. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, InsertRecord) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| CompareRecords(shell(), "text"); |
| InsertRecord(shell(), "text2"); |
| CompareRecords(shell(), "text, text2"); |
| } |
| |
| // Update records in the database. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, UpdateRecord) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| UpdateRecord(shell(), 0, "0"); |
| CompareRecords(shell(), "0"); |
| |
| InsertRecord(shell(), "1"); |
| InsertRecord(shell(), "2"); |
| UpdateRecord(shell(), 1, "1000"); |
| CompareRecords(shell(), "0, 1000, 2"); |
| } |
| |
| // Delete records in the database. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteRecord) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| DeleteRecord(shell(), 0); |
| CompareRecords(shell(), std::string()); |
| |
| InsertRecord(shell(), "0"); |
| InsertRecord(shell(), "1"); |
| InsertRecord(shell(), "2"); |
| DeleteRecord(shell(), 1); |
| CompareRecords(shell(), "0, 2"); |
| } |
| |
| // Attempts to delete a nonexistent row in the table. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteNonexistentRow) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| |
| RunScriptAndCheckResult( |
| shell(), "deleteRecord(1)", "could not find row with index: 1"); |
| |
| CompareRecords(shell(), "text"); |
| } |
| |
| // Insert, update, and delete records in the database. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabaseOperations) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| |
| std::string expected; |
| for (int i = 0; i < 10; ++i) { |
| std::string item = base::IntToString(i); |
| InsertRecord(shell(), item); |
| if (!expected.empty()) |
| expected += ", "; |
| expected += item; |
| } |
| CompareRecords(shell(), expected); |
| |
| expected.clear(); |
| for (int i = 0; i < 10; ++i) { |
| std::string item = base::IntToString(i * i); |
| UpdateRecord(shell(), i, item); |
| if (!expected.empty()) |
| expected += ", "; |
| expected += item; |
| } |
| CompareRecords(shell(), expected); |
| |
| for (int i = 0; i < 10; ++i) |
| DeleteRecord(shell(), 0); |
| |
| CompareRecords(shell(), std::string()); |
| |
| RunScriptAndCheckResult( |
| shell(), "deleteRecord(1)", "could not find row with index: 1"); |
| |
| CompareRecords(shell(), std::string()); |
| } |
| |
| // Create records in the database and verify they persist after reload. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, ReloadPage) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| |
| WindowedNotificationObserver load_stop_observer( |
| NOTIFICATION_LOAD_STOP, |
| NotificationService::AllSources()); |
| shell()->Reload(); |
| load_stop_observer.Wait(); |
| |
| CompareRecords(shell(), "text"); |
| } |
| |
| // Attempt to read a database created in a regular browser from an off the |
| // record browser. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordCannotReadRegularDatabase) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| |
| Shell* otr = CreateOffTheRecordBrowser(); |
| Navigate(otr); |
| ASSERT_FALSE(HasTable(otr)); |
| |
| CreateTable(otr); |
| CompareRecords(otr, std::string()); |
| } |
| |
| // Attempt to read a database created in an off the record browser from a |
| // regular browser. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, RegularCannotReadOffTheRecordDatabase) { |
| Shell* otr = CreateOffTheRecordBrowser(); |
| Navigate(otr); |
| CreateTable(otr); |
| InsertRecord(otr, "text"); |
| |
| Navigate(shell()); |
| ASSERT_FALSE(HasTable(shell())); |
| CreateTable(shell()); |
| CompareRecords(shell(), std::string()); |
| } |
| |
| // Verify DB changes within first window are present in the second window. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationPersistInSecondTab) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| |
| Shell* shell2 = CreateBrowser(); |
| Navigate(shell2); |
| UpdateRecord(shell2, 0, "0"); |
| |
| CompareRecords(shell(), "0"); |
| CompareRecords(shell2, "0"); |
| } |
| |
| // Verify database modifications persist after restarting browser. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_DatabasePersistsAfterRelaunch) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "text"); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabasePersistsAfterRelaunch) { |
| Navigate(shell()); |
| CompareRecords(shell(), "text"); |
| } |
| |
| // Verify OTR database is removed after OTR window closes. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_OffTheRecordDatabaseNotPersistent) { |
| Shell* otr = CreateOffTheRecordBrowser(); |
| Navigate(otr); |
| CreateTable(otr); |
| InsertRecord(otr, "text"); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDatabaseNotPersistent) { |
| Shell* otr = CreateOffTheRecordBrowser(); |
| Navigate(otr); |
| ASSERT_FALSE(HasTable(otr)); |
| } |
| |
| // Verify database modifications persist after crashing window. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationsPersistAfterRendererCrash) { |
| Navigate(shell()); |
| CreateTable(shell()); |
| InsertRecord(shell(), "1"); |
| |
| CrashTab(shell()->web_contents()); |
| Navigate(shell()); |
| CompareRecords(shell(), "1"); |
| } |
| |
| // Test to check if database modifications are persistent across windows in |
| // off the record window. |
| IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDBPersistentAcrossWindows) { |
| Shell* otr1 = CreateOffTheRecordBrowser(); |
| Navigate(otr1); |
| CreateTable(otr1); |
| InsertRecord(otr1, "text"); |
| |
| Shell* otr2 = CreateOffTheRecordBrowser(); |
| Navigate(otr2); |
| CompareRecords(otr2, "text"); |
| } |
| |
| } // namespace content |