Home | History | Annotate | Download | only in browser
      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.
      4 
      5 #include "base/strings/string_number_conversions.h"
      6 #include "base/strings/utf_string_conversions.h"
      7 #include "content/public/browser/browser_context.h"
      8 #include "content/public/browser/download_manager.h"
      9 #include "content/public/browser/notification_service.h"
     10 #include "content/public/browser/notification_types.h"
     11 #include "content/public/browser/web_contents.h"
     12 #include "content/public/test/browser_test_utils.h"
     13 #include "content/public/test/test_utils.h"
     14 #include "content/shell/shell.h"
     15 #include "content/test/content_browser_test.h"
     16 #include "content/test/content_browser_test_utils.h"
     17 #include "content/test/net/url_request_mock_http_job.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace content {
     21 
     22 class DatabaseTest : public ContentBrowserTest {
     23  public:
     24   DatabaseTest() {}
     25 
     26   void RunScriptAndCheckResult(Shell* shell,
     27                                const std::string& script,
     28                                const std::string& result) {
     29     std::string data;
     30     ASSERT_TRUE(ExecuteScriptAndExtractString(
     31         shell->web_contents(),
     32         script,
     33         &data));
     34     ASSERT_EQ(data, result);
     35   }
     36 
     37   void Navigate(Shell* shell) {
     38     NavigateToURL(shell, GetTestUrl("", "simple_database.html"));
     39   }
     40 
     41   void CreateTable(Shell* shell) {
     42     RunScriptAndCheckResult(shell, "createTable()", "done");
     43   }
     44 
     45   void InsertRecord(Shell* shell, const std::string& data) {
     46     RunScriptAndCheckResult(shell, "insertRecord('" + data + "')", "done");
     47   }
     48 
     49   void UpdateRecord(Shell* shell, int index, const std::string& data) {
     50     RunScriptAndCheckResult(
     51         shell,
     52         "updateRecord(" + base::IntToString(index) + ", '" + data + "')",
     53         "done");
     54   }
     55 
     56   void DeleteRecord(Shell* shell, int index) {
     57     RunScriptAndCheckResult(
     58         shell, "deleteRecord(" + base::IntToString(index) + ")", "done");
     59   }
     60 
     61   void CompareRecords(Shell* shell, const std::string& expected) {
     62     RunScriptAndCheckResult(shell, "getRecords()", expected);
     63   }
     64 
     65   bool HasTable(Shell* shell) {
     66     std::string data;
     67     CHECK(ExecuteScriptAndExtractString(
     68         shell->web_contents(),
     69         "getRecords()",
     70         &data));
     71     return data != "getRecords error: [object SQLError]";
     72   }
     73 };
     74 
     75 // Insert records to the database.
     76 IN_PROC_BROWSER_TEST_F(DatabaseTest, InsertRecord) {
     77   Navigate(shell());
     78   CreateTable(shell());
     79   InsertRecord(shell(), "text");
     80   CompareRecords(shell(), "text");
     81   InsertRecord(shell(), "text2");
     82   CompareRecords(shell(), "text, text2");
     83 }
     84 
     85 // Update records in the database.
     86 IN_PROC_BROWSER_TEST_F(DatabaseTest, UpdateRecord) {
     87   Navigate(shell());
     88   CreateTable(shell());
     89   InsertRecord(shell(), "text");
     90   UpdateRecord(shell(), 0, "0");
     91   CompareRecords(shell(), "0");
     92 
     93   InsertRecord(shell(), "1");
     94   InsertRecord(shell(), "2");
     95   UpdateRecord(shell(), 1, "1000");
     96   CompareRecords(shell(), "0, 1000, 2");
     97 }
     98 
     99 // Delete records in the database.
    100 IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteRecord) {
    101   Navigate(shell());
    102   CreateTable(shell());
    103   InsertRecord(shell(), "text");
    104   DeleteRecord(shell(), 0);
    105   CompareRecords(shell(), std::string());
    106 
    107   InsertRecord(shell(), "0");
    108   InsertRecord(shell(), "1");
    109   InsertRecord(shell(), "2");
    110   DeleteRecord(shell(), 1);
    111   CompareRecords(shell(), "0, 2");
    112 }
    113 
    114 // Attempts to delete a nonexistent row in the table.
    115 IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteNonexistentRow) {
    116   Navigate(shell());
    117   CreateTable(shell());
    118   InsertRecord(shell(), "text");
    119 
    120   RunScriptAndCheckResult(
    121       shell(), "deleteRecord(1)", "could not find row with index: 1");
    122 
    123   CompareRecords(shell(), "text");
    124 }
    125 
    126 // Insert, update, and delete records in the database.
    127 IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabaseOperations) {
    128   Navigate(shell());
    129   CreateTable(shell());
    130 
    131   std::string expected;
    132   for (int i = 0; i < 10; ++i) {
    133     std::string item = base::IntToString(i);
    134     InsertRecord(shell(), item);
    135     if (!expected.empty())
    136       expected += ", ";
    137     expected += item;
    138   }
    139   CompareRecords(shell(), expected);
    140 
    141   expected.clear();
    142   for (int i = 0; i < 10; ++i) {
    143     std::string item = base::IntToString(i * i);
    144     UpdateRecord(shell(), i, item);
    145     if (!expected.empty())
    146       expected += ", ";
    147     expected += item;
    148   }
    149   CompareRecords(shell(), expected);
    150 
    151   for (int i = 0; i < 10; ++i)
    152     DeleteRecord(shell(), 0);
    153 
    154   CompareRecords(shell(), std::string());
    155 
    156   RunScriptAndCheckResult(
    157       shell(), "deleteRecord(1)", "could not find row with index: 1");
    158 
    159   CompareRecords(shell(), std::string());
    160 }
    161 
    162 // Create records in the database and verify they persist after reload.
    163 IN_PROC_BROWSER_TEST_F(DatabaseTest, ReloadPage) {
    164   Navigate(shell());
    165   CreateTable(shell());
    166   InsertRecord(shell(), "text");
    167 
    168   WindowedNotificationObserver load_stop_observer(
    169       NOTIFICATION_LOAD_STOP,
    170       NotificationService::AllSources());
    171   shell()->Reload();
    172   load_stop_observer.Wait();
    173 
    174   CompareRecords(shell(), "text");
    175 }
    176 
    177 // Attempt to read a database created in a regular browser from an off the
    178 // record browser.
    179 IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordCannotReadRegularDatabase) {
    180   Navigate(shell());
    181   CreateTable(shell());
    182   InsertRecord(shell(), "text");
    183 
    184   Shell* otr = CreateOffTheRecordBrowser();
    185   Navigate(otr);
    186   ASSERT_FALSE(HasTable(otr));
    187 
    188   CreateTable(otr);
    189   CompareRecords(otr, std::string());
    190 }
    191 
    192 // Attempt to read a database created in an off the record browser from a
    193 // regular browser.
    194 IN_PROC_BROWSER_TEST_F(DatabaseTest, RegularCannotReadOffTheRecordDatabase) {
    195   Shell* otr = CreateOffTheRecordBrowser();
    196   Navigate(otr);
    197   CreateTable(otr);
    198   InsertRecord(otr, "text");
    199 
    200   Navigate(shell());
    201   ASSERT_FALSE(HasTable(shell()));
    202   CreateTable(shell());
    203   CompareRecords(shell(), std::string());
    204 }
    205 
    206 // Verify DB changes within first window are present in the second window.
    207 IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationPersistInSecondTab) {
    208   Navigate(shell());
    209   CreateTable(shell());
    210   InsertRecord(shell(), "text");
    211 
    212   Shell* shell2 = CreateBrowser();
    213   Navigate(shell2);
    214   UpdateRecord(shell2, 0, "0");
    215 
    216   CompareRecords(shell(), "0");
    217   CompareRecords(shell2, "0");
    218 }
    219 
    220 // Verify database modifications persist after restarting browser.
    221 IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_DatabasePersistsAfterRelaunch) {
    222   Navigate(shell());
    223   CreateTable(shell());
    224   InsertRecord(shell(), "text");
    225 }
    226 
    227 IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabasePersistsAfterRelaunch) {
    228   Navigate(shell());
    229   CompareRecords(shell(), "text");
    230 }
    231 
    232 // Verify OTR database is removed after OTR window closes.
    233 IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_OffTheRecordDatabaseNotPersistent) {
    234   Shell* otr = CreateOffTheRecordBrowser();
    235   Navigate(otr);
    236   CreateTable(otr);
    237   InsertRecord(otr, "text");
    238 }
    239 
    240 IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDatabaseNotPersistent) {
    241   Shell* otr = CreateOffTheRecordBrowser();
    242   Navigate(otr);
    243   ASSERT_FALSE(HasTable(otr));
    244 }
    245 
    246 // Verify database modifications persist after crashing window.
    247 IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationsPersistAfterRendererCrash) {
    248   Navigate(shell());
    249   CreateTable(shell());
    250   InsertRecord(shell(), "1");
    251 
    252   CrashTab(shell()->web_contents());
    253   Navigate(shell());
    254   CompareRecords(shell(), "1");
    255 }
    256 
    257 // Test to check if database modifications are persistent across windows in
    258 // off the record window.
    259 IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDBPersistentAcrossWindows) {
    260   Shell* otr1 = CreateOffTheRecordBrowser();
    261   Navigate(otr1);
    262   CreateTable(otr1);
    263   InsertRecord(otr1, "text");
    264 
    265   Shell* otr2 = CreateOffTheRecordBrowser();
    266   Navigate(otr2);
    267   CompareRecords(otr2, "text");
    268 }
    269 
    270 }  // namespace content
    271