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