1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
content / browser / dom_storage / dom_storage_browsertest.cc [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/services/storage/dom_storage/local_storage_impl.h"
#include "components/services/storage/dom_storage/storage_area_impl.h"
#include "components/services/storage/public/cpp/constants.h"
#include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/storage_usage_info.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.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_launcher.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
namespace content {
// This browser test is aimed towards exercising the DOMStorage system
// from end-to-end.
class DOMStorageBrowserTest : public ContentBrowserTest {
public:
DOMStorageBrowserTest() {}
void SimpleTest(const GURL& test_url, bool incognito) {
// The test page will perform tests then navigate to either
// a #pass or #fail ref.
Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell();
NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
std::string result =
the_browser->web_contents()->GetLastCommittedURL().ref();
if (result != "pass") {
std::string js_result = EvalJs(the_browser, "getLog()").ExtractString();
FAIL() << "Failed: " << js_result;
}
}
StoragePartition* partition() {
return shell()
->web_contents()
->GetBrowserContext()
->GetDefaultStoragePartition();
}
std::vector<StorageUsageInfo> GetUsage() {
base::RunLoop loop;
std::vector<StorageUsageInfo> usage;
partition()->GetDOMStorageContext()->GetLocalStorageUsage(
base::BindLambdaForTesting([&](const std::vector<StorageUsageInfo>& u) {
usage = u;
loop.Quit();
}));
loop.Run();
return usage;
}
void DeletePhysicalStorageKey(blink::StorageKey storage_key) {
base::RunLoop loop;
partition()->GetDOMStorageContext()->DeleteLocalStorage(storage_key,
loop.QuitClosure());
loop.Run();
}
DOMStorageContextWrapper* context_wrapper() {
return static_cast<DOMStorageContextWrapper*>(
partition()->GetDOMStorageContext());
}
};
static const bool kIncognito = true;
static const bool kNotIncognito = false;
IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, SanityCheck) {
SimpleTest(GetTestUrl("dom_storage", "sanity_check.html"), kNotIncognito);
}
IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, SanityCheckIncognito) {
SimpleTest(GetTestUrl("dom_storage", "sanity_check.html"), kIncognito);
}
// http://crbug.com/654704 PRE_ tests aren't supported on Android.
// TODO(crbug.com/40885339): Re-enable this test for fuchsia.
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
#define MAYBE_DataPersists DISABLED_DataPersists
#else
#define MAYBE_DataPersists DataPersists
#endif
IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, PRE_DataPersists) {
SimpleTest(GetTestUrl("dom_storage", "store_data.html"), kNotIncognito);
// Browser shutdown can always race with async work on non-shutdown-blocking
// task runners. This includes the local storage implementation. If opening
// the database takes too long, by the time it finishes the IO thread may be
// shut down and the Local Storage implementation may be unable to commit its
// pending operations.
//
// Since the point of this test is to verify that committed data is actually
// retrievable by a subsequent browser session, wait for the database to be
// ready.
base::RunLoop loop;
context_wrapper()->GetLocalStorageUsage(base::BindLambdaForTesting(
[&](const std::vector<StorageUsageInfo>&) { loop.Quit(); }));
loop.Run();
}
IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, MAYBE_DataPersists) {
SimpleTest(GetTestUrl("dom_storage", "verify_data.html"), kNotIncognito);
}
// TODO(crbug/361107780): Fix flakiness on android-bfcache-rel and re-enable.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_DeletePhysicalStorageKey DISABLED_DeletePhysicalStorageKey
#else
#define MAYBE_DeletePhysicalStorageKey DeletePhysicalStorageKey
#endif
IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, MAYBE_DeletePhysicalStorageKey) {
EXPECT_EQ(0U, GetUsage().size());
SimpleTest(GetTestUrl("dom_storage", "store_data.html"), kNotIncognito);
std::vector<StorageUsageInfo> usage = GetUsage();
ASSERT_EQ(1U, usage.size());
DeletePhysicalStorageKey(usage[0].storage_key);
EXPECT_EQ(0U, GetUsage().size());
}
// On Windows file://localhost/C:/src/chromium/src/content/test/data/title1.html
// doesn't work.
#if !BUILDFLAG(IS_WIN)
// Regression test for https://crbug.com/776160. The test verifies that there
// is no disagreement between 1) site URL used for browser-side isolation
// enforcement and 2) the origin requested by Blink. Before this bug was fixed,
// (1) was file://localhost/ and (2) was file:// - this led to renderer kills.
IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, FileUrlWithHost) {
// Navigate to file://localhost/.../title1.html
GURL regular_file_url = GetTestUrl(nullptr, "title1.html");
GURL::Replacements host_replacement;
host_replacement.SetHostStr("localhost");
GURL file_with_host_url =
regular_file_url.ReplaceComponents(host_replacement);
EXPECT_TRUE(NavigateToURL(shell(), file_with_host_url));
EXPECT_THAT(shell()->web_contents()->GetLastCommittedURL().spec(),
testing::StartsWith("file://localhost/"));
EXPECT_THAT(shell()->web_contents()->GetLastCommittedURL().spec(),
testing::EndsWith("/title1.html"));
// Verify that window.localStorage works fine.
std::string script = R"(
localStorage["foo"] = "bar";
localStorage["foo"];
)";
EXPECT_EQ("bar", EvalJs(shell(), script));
}
#endif
class DomStorageSmartFlushingBrowserTest : public DOMStorageBrowserTest {
private:
base::test::ScopedFeatureList feature_{storage::kDomStorageSmartFlushing};
};
// Flaky on Chrome OS.
#if !BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(DomStorageSmartFlushingBrowserTest, DataWrittenQuickly) {
// The first write should get flushed quickly due to Checkpoint().
SimpleTest(GetTestUrl("dom_storage", "store_data.html"), kNotIncognito);
base::test::TestFuture<bool> result;
context_wrapper()->GetLocalStorageControl()->NeedsFlushForTesting(
result.GetCallback());
EXPECT_FALSE(result.Take());
// Subsequent writes usually get delayed a bit due to commit throttling, but
// that's difficult to verify in a non-flaky manner.
}
#endif
} // namespace content