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