database_browsertest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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/content_browser_test.h"
14#include "content/public/test/content_browser_test_utils.h"
15#include "content/public/test/test_utils.h"
16#include "content/shell/browser/shell.h"
17#include "content/test/net/url_request_mock_http_job.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20namespace content {
21
22class 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.
76IN_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.
86IN_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.
100IN_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.
115IN_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.
127IN_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.
163IN_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.
179IN_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.
194IN_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.
207IN_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.
221IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_DatabasePersistsAfterRelaunch) {
222  Navigate(shell());
223  CreateTable(shell());
224  InsertRecord(shell(), "text");
225}
226
227IN_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.
233IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_OffTheRecordDatabaseNotPersistent) {
234  Shell* otr = CreateOffTheRecordBrowser();
235  Navigate(otr);
236  CreateTable(otr);
237  InsertRecord(otr, "text");
238}
239
240IN_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.
247IN_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.
259IN_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