1 // Copyright 2020 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 "weblayer/browser/persistence/browser_persister.h"
6
7 #include "base/callback_helpers.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/guid.h"
11 #include "base/path_service.h"
12 #include "base/run_loop.h"
13 #include "base/test/bind.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "build/build_config.h"
16 #include "components/sessions/core/command_storage_manager_test_helper.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "content/public/test/url_loader_interceptor.h"
19 #include "net/base/filename_util.h"
20 #include "net/test/embedded_test_server/embedded_test_server.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "weblayer/browser/browser_impl.h"
23 #include "weblayer/browser/persistence/browser_persister_file_utils.h"
24 #include "weblayer/browser/profile_impl.h"
25 #include "weblayer/browser/tab_impl.h"
26 #include "weblayer/common/weblayer_paths.h"
27 #include "weblayer/public/browser_restore_observer.h"
28 #include "weblayer/public/navigation.h"
29 #include "weblayer/public/navigation_controller.h"
30 #include "weblayer/public/navigation_observer.h"
31 #include "weblayer/public/tab.h"
32 #include "weblayer/shell/browser/shell.h"
33 #include "weblayer/test/interstitial_utils.h"
34 #include "weblayer/test/test_navigation_observer.h"
35 #include "weblayer/test/weblayer_browser_test.h"
36 #include "weblayer/test/weblayer_browser_test_utils.h"
37
38 namespace weblayer {
39
40 class BrowserPersisterTestHelper {
41 public:
GetCommandStorageManager(BrowserPersister * persister)42 static sessions::CommandStorageManager* GetCommandStorageManager(
43 BrowserPersister* persister) {
44 return persister->command_storage_manager_.get();
45 }
46 };
47
48 namespace {
49 using testing::UnorderedElementsAre;
50
51 class BrowserNavigationObserverImpl : public BrowserRestoreObserver,
52 public NavigationObserver {
53 public:
WaitForNewTabToCompleteNavigation(Browser * browser,const GURL & url,size_t tab_to_wait_for=0)54 static void WaitForNewTabToCompleteNavigation(Browser* browser,
55 const GURL& url,
56 size_t tab_to_wait_for = 0) {
57 BrowserNavigationObserverImpl observer(browser, url, tab_to_wait_for);
58 observer.Wait();
59 }
60
61 private:
BrowserNavigationObserverImpl(Browser * browser,const GURL & url,size_t tab_to_wait_for)62 BrowserNavigationObserverImpl(Browser* browser,
63 const GURL& url,
64 size_t tab_to_wait_for)
65 : browser_(browser), url_(url), tab_to_wait_for_(tab_to_wait_for) {
66 browser_->AddBrowserRestoreObserver(this);
67 }
~BrowserNavigationObserverImpl()68 ~BrowserNavigationObserverImpl() override {
69 tab_->GetNavigationController()->RemoveObserver(this);
70 }
71
Wait()72 void Wait() { run_loop_.Run(); }
73
74 // NavigationObserver;
NavigationCompleted(Navigation * navigation)75 void NavigationCompleted(Navigation* navigation) override {
76 if (navigation->GetURL() == url_)
77 run_loop_.Quit();
78 }
79
80 // BrowserRestoreObserver:
OnRestoreCompleted()81 void OnRestoreCompleted() override {
82 browser_->RemoveBrowserRestoreObserver(this);
83 ASSERT_LT(tab_to_wait_for_, browser_->GetTabs().size());
84 ASSERT_EQ(nullptr, tab_);
85 tab_ = browser_->GetTabs()[tab_to_wait_for_];
86 tab_->GetNavigationController()->AddObserver(this);
87 }
88
89 Browser* browser_;
90 const GURL& url_;
91 Tab* tab_ = nullptr;
92 const size_t tab_to_wait_for_;
93 std::unique_ptr<TestNavigationObserver> navigation_observer_;
94 base::RunLoop run_loop_;
95 };
96
ShutdownBrowserPersisterAndWait(BrowserImpl * browser)97 void ShutdownBrowserPersisterAndWait(BrowserImpl* browser) {
98 auto task_runner = sessions::CommandStorageManagerTestHelper(
99 BrowserPersisterTestHelper::GetCommandStorageManager(
100 browser->browser_persister()))
101 .GetBackendTaskRunner();
102 browser->PrepareForShutdown();
103 base::RunLoop run_loop;
104 task_runner->PostTaskAndReply(FROM_HERE, base::DoNothing(),
105 run_loop.QuitClosure());
106 run_loop.Run();
107 }
108
CreateBrowser(ProfileImpl * profile,const std::string & persistence_id)109 std::unique_ptr<BrowserImpl> CreateBrowser(ProfileImpl* profile,
110 const std::string& persistence_id) {
111 Browser::PersistenceInfo info;
112 info.id = persistence_id;
113 auto browser = Browser::Create(profile, &info);
114 return std::unique_ptr<BrowserImpl>(
115 static_cast<BrowserImpl*>(browser.release()));
116 }
117
118 } // namespace
119
120 using BrowserPersisterTest = WebLayerBrowserTest;
121
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest,SingleTab)122 IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, SingleTab) {
123 ASSERT_TRUE(embedded_test_server()->Start());
124
125 std::unique_ptr<BrowserImpl> browser = CreateBrowser(GetProfile(), "x");
126 Tab* tab = browser->CreateTab();
127 EXPECT_TRUE(browser->IsRestoringPreviousState());
128 const GURL url = embedded_test_server()->GetURL("/simple_page.html");
129 NavigateAndWaitForCompletion(url, tab);
130 ShutdownBrowserPersisterAndWait(browser.get());
131 tab = nullptr;
132 browser.reset();
133
134 browser = CreateBrowser(GetProfile(), "x");
135 // Should be no tabs while waiting for restore.
136 EXPECT_TRUE(browser->GetTabs().empty());
137 EXPECT_TRUE(browser->IsRestoringPreviousState());
138 // Wait for the restore and navigation to complete.
139 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
140 browser.get(), url);
141
142 ASSERT_EQ(1u, browser->GetTabs().size());
143 EXPECT_EQ(browser->GetTabs()[0], browser->GetActiveTab());
144 EXPECT_EQ(1, browser->GetTabs()[0]
145 ->GetNavigationController()
146 ->GetNavigationListSize());
147 EXPECT_FALSE(browser->IsRestoringPreviousState());
148 }
149
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest,RestoresGuid)150 IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, RestoresGuid) {
151 ASSERT_TRUE(embedded_test_server()->Start());
152
153 std::unique_ptr<BrowserImpl> browser = CreateBrowser(GetProfile(), "x");
154 Tab* tab = browser->CreateTab();
155 const std::string original_guid = tab->GetGuid();
156 EXPECT_FALSE(original_guid.empty());
157 EXPECT_TRUE(base::IsValidGUID(original_guid));
158 const GURL url = embedded_test_server()->GetURL("/simple_page.html");
159 NavigateAndWaitForCompletion(url, tab);
160 ShutdownBrowserPersisterAndWait(browser.get());
161 tab = nullptr;
162 browser.reset();
163
164 browser = CreateBrowser(GetProfile(), "x");
165 // Should be no tabs while waiting for restore.
166 EXPECT_TRUE(browser->GetTabs().empty());
167 // Wait for the restore and navigation to complete.
168 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
169 browser.get(), url);
170
171 ASSERT_EQ(1u, browser->GetTabs().size());
172 EXPECT_EQ(browser->GetTabs()[0], browser->GetActiveTab());
173 EXPECT_EQ(original_guid, browser->GetTabs()[0]->GetGuid());
174 }
175
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest,RestoresData)176 IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, RestoresData) {
177 ASSERT_TRUE(embedded_test_server()->Start());
178
179 std::unique_ptr<BrowserImpl> browser = CreateBrowser(GetProfile(), "x");
180 Tab* tab = browser->CreateTab();
181 tab->SetData({{"abc", "efg"}});
182 const GURL url = embedded_test_server()->GetURL("/simple_page.html");
183 NavigateAndWaitForCompletion(url, tab);
184 ShutdownBrowserPersisterAndWait(browser.get());
185 tab = nullptr;
186 browser.reset();
187
188 browser = CreateBrowser(GetProfile(), "x");
189 // Should be no tabs while waiting for restore.
190 EXPECT_TRUE(browser->GetTabs().empty());
191 // Wait for the restore and navigation to complete.
192 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
193 browser.get(), url);
194
195 ASSERT_EQ(1u, browser->GetTabs().size());
196 EXPECT_EQ(browser->GetTabs()[0], browser->GetActiveTab());
197 EXPECT_THAT(browser->GetTabs()[0]->GetData(),
198 UnorderedElementsAre(std::make_pair("abc", "efg")));
199 }
200
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest,RestoresMostRecentData)201 IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, RestoresMostRecentData) {
202 ASSERT_TRUE(embedded_test_server()->Start());
203
204 std::unique_ptr<BrowserImpl> browser = CreateBrowser(GetProfile(), "x");
205 Tab* tab = browser->CreateTab();
206 tab->SetData({{"xxx", "xxx"}});
207 const GURL url = embedded_test_server()->GetURL("/simple_page.html");
208 NavigateAndWaitForCompletion(url, tab);
209
210 // Make sure the data has been saved, then set different data on the tab.
211 BrowserPersisterTestHelper::GetCommandStorageManager(
212 browser->browser_persister())
213 ->Save();
214 tab->SetData({{"abc", "efg"}});
215
216 ShutdownBrowserPersisterAndWait(browser.get());
217 tab = nullptr;
218 browser.reset();
219
220 browser = CreateBrowser(GetProfile(), "x");
221 // Should be no tabs while waiting for restore.
222 EXPECT_TRUE(browser->GetTabs().empty());
223 // Wait for the restore and navigation to complete.
224 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
225 browser.get(), url);
226
227 ASSERT_EQ(1u, browser->GetTabs().size());
228 EXPECT_EQ(browser->GetTabs()[0], browser->GetActiveTab());
229 EXPECT_THAT(browser->GetTabs()[0]->GetData(),
230 UnorderedElementsAre(std::make_pair("abc", "efg")));
231 }
232
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest,TwoTabs)233 IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, TwoTabs) {
234 ASSERT_TRUE(embedded_test_server()->Start());
235
236 std::unique_ptr<BrowserImpl> browser = CreateBrowser(GetProfile(), "x");
237 Tab* tab1 = browser->CreateTab();
238 const GURL url1 = embedded_test_server()->GetURL("/simple_page.html");
239 NavigateAndWaitForCompletion(url1, tab1);
240
241 Tab* tab2 = browser->CreateTab();
242 const GURL url2 = embedded_test_server()->GetURL("/simple_page2.html");
243 NavigateAndWaitForCompletion(url2, tab2);
244 browser->SetActiveTab(tab2);
245
246 // Shut down the service.
247 ShutdownBrowserPersisterAndWait(browser.get());
248 tab1 = tab2 = nullptr;
249 browser.reset();
250
251 // Recreate the browser and run the assertions twice to ensure we handle
252 // correctly storing state of tabs that need to be reloaded.
253 for (int i = 0; i < 2; ++i) {
254 browser = CreateBrowser(GetProfile(), "x");
255 // Should be no tabs while waiting for restore.
256 EXPECT_TRUE(browser->GetTabs().empty()) << "iteration " << i;
257 // Wait for the restore and navigation to complete. This waits for the
258 // second tab as that was the active one.
259 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
260 browser.get(), url2, 1);
261
262 ASSERT_EQ(2u, browser->GetTabs().size()) << "iteration " << i;
263 // The first tab shouldn't have loaded yet, as it's not active.
264 EXPECT_TRUE(static_cast<TabImpl*>(browser->GetTabs()[0])
265 ->web_contents()
266 ->GetController()
267 .NeedsReload())
268 << "iteration " << i;
269 EXPECT_EQ(browser->GetTabs()[1], browser->GetActiveTab())
270 << "iteration " << i;
271 EXPECT_EQ(1, browser->GetTabs()[1]
272 ->GetNavigationController()
273 ->GetNavigationListSize())
274 << "iteration " << i;
275
276 ShutdownBrowserPersisterAndWait(browser.get());
277 }
278 }
279
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest,MoveBetweenBrowsers)280 IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, MoveBetweenBrowsers) {
281 ASSERT_TRUE(embedded_test_server()->Start());
282
283 // Create a browser with two tabs.
284 std::unique_ptr<BrowserImpl> browser1 = CreateBrowser(GetProfile(), "x");
285 Tab* tab1 = browser1->CreateTab();
286 const GURL url1 = embedded_test_server()->GetURL("/simple_page.html");
287 NavigateAndWaitForCompletion(url1, tab1);
288
289 Tab* tab2 = browser1->CreateTab();
290 const GURL url2 = embedded_test_server()->GetURL("/simple_page2.html");
291 NavigateAndWaitForCompletion(url2, tab2);
292 browser1->SetActiveTab(tab2);
293
294 // Create another browser with a single tab.
295 std::unique_ptr<BrowserImpl> browser2 = CreateBrowser(GetProfile(), "y");
296 Tab* tab3 = browser2->CreateTab();
297 const GURL url3 = embedded_test_server()->GetURL("/simple_page3.html");
298 NavigateAndWaitForCompletion(url3, tab3);
299
300 // Move |tab2| to |browser2|.
301 browser2->AddTab(tab2);
302 browser2->SetActiveTab(tab2);
303
304 ShutdownBrowserPersisterAndWait(browser1.get());
305 ShutdownBrowserPersisterAndWait(browser2.get());
306 tab1 = nullptr;
307 browser1.reset();
308
309 tab2 = tab3 = nullptr;
310 browser2.reset();
311
312 // Restore the browsers.
313 browser1 = CreateBrowser(GetProfile(), "x");
314 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
315 browser1.get(), url1);
316 ASSERT_EQ(1u, browser1->GetTabs().size());
317 EXPECT_EQ(1, browser1->GetTabs()[0]
318 ->GetNavigationController()
319 ->GetNavigationListSize());
320
321 browser2 = CreateBrowser(GetProfile(), "y");
322 BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
323 browser2.get(), url2, 1);
324 ASSERT_EQ(2u, browser2->GetTabs().size());
325 EXPECT_EQ(1, browser2->GetTabs()[1]
326 ->GetNavigationController()
327 ->GetNavigationListSize());
328
329 // As |tab3| isn't active it needs to be loaded. Force that now.
330 TabImpl* restored_tab_3 = static_cast<TabImpl*>(browser2->GetTabs()[0]);
331 EXPECT_TRUE(restored_tab_3->web_contents()->GetController().NeedsReload());
332 restored_tab_3->web_contents()->GetController().LoadIfNecessary();
333 EXPECT_TRUE(content::WaitForLoadStop(restored_tab_3->web_contents()));
334 }
335
336 class BrowserPersisterTestWithTwoPersistedIds : public WebLayerBrowserTest {
337 public:
338 // WebLayerBrowserTest:
SetUpOnMainThread()339 void SetUpOnMainThread() override {
340 WebLayerBrowserTest::SetUpOnMainThread();
341 // Configure two browsers with ids 'x' and 'y'.
342 ASSERT_TRUE(embedded_test_server()->Start());
343 std::unique_ptr<BrowserImpl> browser1 = CreateBrowser(GetProfile(), "x");
344 const GURL url1 = embedded_test_server()->GetURL("/simple_page.html");
345 NavigateAndWaitForCompletion(url1, browser1->CreateTab());
346
347 std::unique_ptr<BrowserImpl> browser2 = CreateBrowser(GetProfile(), "y");
348 const GURL url2 = embedded_test_server()->GetURL("/simple_page3.html");
349 NavigateAndWaitForCompletion(url2, browser2->CreateTab());
350
351 // Shut down the browsers.
352 ShutdownBrowserPersisterAndWait(browser1.get());
353 browser1.reset();
354 ShutdownBrowserPersisterAndWait(browser2.get());
355 browser2.reset();
356 }
357 };
358
IN_PROC_BROWSER_TEST_F(BrowserPersisterTestWithTwoPersistedIds,GetBrowserPersistenceIds)359 IN_PROC_BROWSER_TEST_F(BrowserPersisterTestWithTwoPersistedIds,
360 GetBrowserPersistenceIds) {
361 {
362 // Create a file that has the name of a valid persistence file, but has
363 // invalid contents.
364 base::ScopedAllowBlockingForTesting allow_blocking;
365 base::WriteFile(BuildPathForBrowserPersister(
366 GetProfile()->GetBrowserPersisterDataBaseDir(), "z"),
367 "a bogus persistence file");
368 }
369
370 base::RunLoop run_loop;
371 base::flat_set<std::string> persistence_ids;
372 GetProfile()->GetBrowserPersistenceIds(
373 base::BindLambdaForTesting([&](base::flat_set<std::string> ids) {
374 persistence_ids = std::move(ids);
375 run_loop.Quit();
376 }));
377 run_loop.Run();
378 ASSERT_EQ(2u, persistence_ids.size());
379 EXPECT_TRUE(persistence_ids.contains("x"));
380 EXPECT_TRUE(persistence_ids.contains("y"));
381 }
382
IN_PROC_BROWSER_TEST_F(BrowserPersisterTestWithTwoPersistedIds,RemoveBrowserPersistenceStorage)383 IN_PROC_BROWSER_TEST_F(BrowserPersisterTestWithTwoPersistedIds,
384 RemoveBrowserPersistenceStorage) {
385 base::FilePath file_path1 = BuildPathForBrowserPersister(
386 GetProfile()->GetBrowserPersisterDataBaseDir(), "x");
387 base::FilePath file_path2 = BuildPathForBrowserPersister(
388 GetProfile()->GetBrowserPersisterDataBaseDir(), "y");
389
390 {
391 base::ScopedAllowBlockingForTesting allow_blocking;
392 ASSERT_TRUE(base::PathExists(file_path1));
393 ASSERT_TRUE(base::PathExists(file_path2));
394 }
395 base::RunLoop run_loop;
396 base::flat_set<std::string> persistence_ids;
397 persistence_ids.insert("x");
398 persistence_ids.insert("y");
399 GetProfile()->RemoveBrowserPersistenceStorage(
400 base::BindLambdaForTesting([&](bool result) {
401 EXPECT_TRUE(result);
402 run_loop.Quit();
403 }),
404 std::move(persistence_ids));
405 run_loop.Run();
406 {
407 base::ScopedAllowBlockingForTesting allow_blocking;
408 EXPECT_FALSE(base::PathExists(file_path1));
409 EXPECT_FALSE(base::PathExists(file_path2));
410 }
411 }
412
413 } // namespace weblayer
414