@@ -44,6 +44,11 @@ class ContainersBrowserTest : public InProcessBrowserTest {
4444
4545 ~ContainersBrowserTest () override = default ;
4646
47+ void SetUp () override {
48+ set_open_about_blank_on_browser_launch (false );
49+ InProcessBrowserTest::SetUp ();
50+ }
51+
4752 void SetUpCommandLine (base::CommandLine* command_line) override {
4853 InProcessBrowserTest::SetUpCommandLine (command_line);
4954 command_line->AppendSwitchASCII (
@@ -328,6 +333,73 @@ IN_PROC_BROWSER_TEST_F(ContainersBrowserTest, IsolateCookiesAndStorage) {
328333 GetIndexedDBJS (" test_key" )));
329334}
330335
336+ IN_PROC_BROWSER_TEST_F (ContainersBrowserTest,
337+ PRE_StoragePersistenceAcrossSessions) {
338+ const GURL url (" https://a.test/simple.html" );
339+
340+ // Navigate to the page
341+ NavigateParams params (browser (), url, ui::PAGE_TRANSITION_LINK);
342+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
343+ params.storage_partition_config = content::StoragePartitionConfig::Create (
344+ browser ()->profile (), kContainersStoragePartitionDomain , " container" ,
345+ browser ()->profile ()->IsOffTheRecord ());
346+ ui_test_utils::NavigateToURL (¶ms);
347+
348+ content::WebContents* web_contents =
349+ browser ()->tab_strip_model ()->GetActiveWebContents ();
350+ ASSERT_TRUE (web_contents);
351+
352+ // Set persistent storage data
353+ EXPECT_TRUE (content::ExecJs (
354+ web_contents, SetCookieJS (" persistent_cookie" , " persistent_value" )));
355+ EXPECT_TRUE (content::ExecJs (
356+ web_contents, SetLocalStorageJS (" persistent_key" , " persistent_value" )));
357+
358+ EXPECT_TRUE (content::ExecJs (
359+ web_contents, SetIndexedDBJS (" persistent_key" , " persistent_value" )));
360+
361+ // Verify data is set
362+ content::EvalJsResult cookie_result =
363+ content::EvalJs (web_contents, GetCookiesJS ());
364+ EXPECT_TRUE (cookie_result.ExtractString ().find (
365+ " persistent_cookie=persistent_value" ) != std::string::npos);
366+
367+ EXPECT_EQ (" persistent_value" ,
368+ content::EvalJs (web_contents, GetLocalStorageJS (" persistent_key" )));
369+ EXPECT_EQ (" persistent_value" ,
370+ content::EvalJs (web_contents, GetIndexedDBJS (" persistent_key" )));
371+ }
372+
373+ IN_PROC_BROWSER_TEST_F (ContainersBrowserTest,
374+ StoragePersistenceAcrossSessions) {
375+ const GURL url (" https://a.test/simple.html" );
376+
377+ // Navigate to the page
378+ NavigateParams params (browser (), url, ui::PAGE_TRANSITION_LINK);
379+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
380+ params.storage_partition_config = content::StoragePartitionConfig::Create (
381+ browser ()->profile (), kContainersStoragePartitionDomain , " container" ,
382+ browser ()->profile ()->IsOffTheRecord ());
383+ ui_test_utils::NavigateToURL (¶ms);
384+
385+ content::WebContents* web_contents_reloaded =
386+ browser ()->tab_strip_model ()->GetActiveWebContents ();
387+ ASSERT_TRUE (web_contents_reloaded);
388+
389+ // Verify persistent data is still available after reload
390+ content::EvalJsResult cookie_result_reloaded =
391+ content::EvalJs (web_contents_reloaded, GetCookiesJS ());
392+ EXPECT_TRUE (cookie_result_reloaded.ExtractString ().find (
393+ " persistent_cookie=persistent_value" ) != std::string::npos);
394+
395+ EXPECT_EQ (" persistent_value" ,
396+ content::EvalJs (web_contents_reloaded,
397+ GetLocalStorageJS (" persistent_key" )));
398+ EXPECT_EQ (
399+ " persistent_value" ,
400+ content::EvalJs (web_contents_reloaded, GetIndexedDBJS (" persistent_key" )));
401+ }
402+
331403IN_PROC_BROWSER_TEST_F (ContainersBrowserTest,
332404 LinkNavigationInheritsContainerStoragePartition) {
333405 const GURL url (" https://a.test/simple.html" );
@@ -417,7 +489,8 @@ IN_PROC_BROWSER_TEST_F(ContainersBrowserTest,
417489 GetIndexedDBJS (" new_tab_key" )));
418490}
419491
420- IN_PROC_BROWSER_TEST_F (ContainersBrowserTest, IsolateServiceWorkers) {
492+ IN_PROC_BROWSER_TEST_F (ContainersBrowserTest,
493+ IsolateServiceWorkersBetweenContainers) {
421494 const GURL url (" https://a.test/containers/container_test.html" );
422495 const GURL worker_url (" https://a.test/containers/container_worker.js" );
423496 const std::string scope = " https://a.test/containers/" ;
@@ -851,4 +924,174 @@ IN_PROC_BROWSER_TEST_F(ContainersBrowserTest,
851924 // container
852925}
853926
927+ IN_PROC_BROWSER_TEST_F (ContainersBrowserTest,
928+ PRE_ServiceWorkerPersistenceAcrossSessions) {
929+ const GURL url (" https://a.test/containers/container_test.html" );
930+ const GURL worker_url (" https://a.test/containers/container_worker.js" );
931+ const std::string scope = " https://a.test/containers/" ;
932+
933+ // Navigate to the page with a container
934+ NavigateParams params (browser (), url, ui::PAGE_TRANSITION_LINK);
935+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
936+ params.storage_partition_config = content::StoragePartitionConfig::Create (
937+ browser ()->profile (), kContainersStoragePartitionDomain ,
938+ " persistent-container" , browser ()->profile ()->IsOffTheRecord ());
939+ ui_test_utils::NavigateToURL (¶ms);
940+
941+ content::WebContents* web_contents =
942+ browser ()->tab_strip_model ()->GetActiveWebContents ();
943+ ASSERT_TRUE (web_contents);
944+
945+ // Register service worker
946+ EXPECT_TRUE (content::ExecJs (
947+ web_contents, RegisterServiceWorkerJS (worker_url.spec (), scope)));
948+
949+ // Verify service worker is registered
950+ EXPECT_EQ (
951+ " registered" ,
952+ content::EvalJs (web_contents, CheckServiceWorkerRegisteredJS (scope)));
953+
954+ // Set some persistent storage data that the service worker might use
955+ EXPECT_TRUE (content::ExecJs (
956+ web_contents, SetLocalStorageJS (" sw_data" , " persistent_value" )));
957+ EXPECT_TRUE (content::ExecJs (web_contents,
958+ SetCookieJS (" sw_cookie" , " persistent_cookie" )));
959+ }
960+
961+ IN_PROC_BROWSER_TEST_F (ContainersBrowserTest,
962+ ServiceWorkerPersistenceAcrossSessions) {
963+ const GURL url (" https://a.test/containers/container_test.html" );
964+ const std::string scope = " https://a.test/containers/" ;
965+
966+ // Navigate to the page with the same container
967+ NavigateParams params (browser (), url, ui::PAGE_TRANSITION_LINK);
968+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
969+ params.storage_partition_config = content::StoragePartitionConfig::Create (
970+ browser ()->profile (), kContainersStoragePartitionDomain ,
971+ " persistent-container" , browser ()->profile ()->IsOffTheRecord ());
972+ ui_test_utils::NavigateToURL (¶ms);
973+
974+ content::WebContents* web_contents_reloaded =
975+ browser ()->tab_strip_model ()->GetActiveWebContents ();
976+ ASSERT_TRUE (web_contents_reloaded);
977+
978+ // Verify service worker is still registered after browser restart
979+ EXPECT_EQ (" registered" ,
980+ content::EvalJs (web_contents_reloaded,
981+ CheckServiceWorkerRegisteredJS (scope)));
982+
983+ // Verify persistent storage data is still available
984+ EXPECT_EQ (" persistent_value" , content::EvalJs (web_contents_reloaded,
985+ GetLocalStorageJS (" sw_data" )));
986+
987+ content::EvalJsResult cookie_result =
988+ content::EvalJs (web_contents_reloaded, GetCookiesJS ());
989+ EXPECT_TRUE (cookie_result.ExtractString ().find (
990+ " sw_cookie=persistent_cookie" ) != std::string::npos);
991+ }
992+
993+ // Test suite to verify behavior when containers feature is disabled after
994+ // a session with container tabs.
995+ class ContainersDisabledAfterRestoreBrowserTest : public ContainersBrowserTest {
996+ public:
997+ ContainersDisabledAfterRestoreBrowserTest () {
998+ const ::testing::TestInfo* test_info =
999+ ::testing::UnitTest::GetInstance ()->current_test_info();
1000+ std::string test_name = test_info->name ();
1001+
1002+ if (!test_name.starts_with (" PRE_" )) {
1003+ feature_list_override_.InitAndDisableFeature (features::kContainers );
1004+ }
1005+ }
1006+
1007+ protected:
1008+ base::test::ScopedFeatureList feature_list_override_;
1009+ };
1010+
1011+ IN_PROC_BROWSER_TEST_F (ContainersDisabledAfterRestoreBrowserTest,
1012+ PRE_RestoreWithDefaultPartition) {
1013+ const GURL url (" https://a.test/simple.html" );
1014+
1015+ // Navigate to the page with a container storage partition
1016+ NavigateParams params (browser (), url, ui::PAGE_TRANSITION_LINK);
1017+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
1018+ params.storage_partition_config = content::StoragePartitionConfig::Create (
1019+ browser ()->profile (), kContainersStoragePartitionDomain , " test-container" ,
1020+ browser ()->profile ()->IsOffTheRecord ());
1021+ ui_test_utils::NavigateToURL (¶ms);
1022+
1023+ content::WebContents* web_contents =
1024+ browser ()->tab_strip_model ()->GetActiveWebContents ();
1025+ ASSERT_TRUE (web_contents);
1026+
1027+ // Verify we're using a container storage partition
1028+ content::StoragePartition* storage_partition =
1029+ web_contents->GetPrimaryMainFrame ()->GetStoragePartition ();
1030+ ASSERT_TRUE (storage_partition);
1031+
1032+ EXPECT_EQ (storage_partition->GetConfig ().partition_domain (),
1033+ kContainersStoragePartitionDomain );
1034+ EXPECT_EQ (storage_partition->GetConfig ().partition_name (), " test-container" );
1035+
1036+ // Set some storage data in the container
1037+ EXPECT_TRUE (content::ExecJs (web_contents,
1038+ SetCookieJS (" test_cookie" , " container_value" )));
1039+ EXPECT_TRUE (content::ExecJs (
1040+ web_contents, SetLocalStorageJS (" test_key" , " container_value" )));
1041+ }
1042+
1043+ IN_PROC_BROWSER_TEST_F (ContainersDisabledAfterRestoreBrowserTest,
1044+ RestoreWithDefaultPartition) {
1045+ // At this point, containers feature is disabled, but we have a restored tab
1046+ // that was previously in a container
1047+
1048+ content::WebContents* web_contents =
1049+ browser ()->tab_strip_model ()->GetActiveWebContents ();
1050+ ASSERT_TRUE (web_contents);
1051+
1052+ // Verify the URL scheme has been changed to containers-default+...
1053+ GURL current_url = web_contents->GetLastCommittedURL ();
1054+ std::string url_scheme = std::string (current_url.scheme ());
1055+
1056+ // The URL should have a scheme like "containers-default+https"
1057+ EXPECT_TRUE (url_scheme.starts_with (" containers-default+" )) << url_scheme;
1058+
1059+ // Verify the storage partition is now the default one, not a container
1060+ // partition
1061+ content::StoragePartition* storage_partition =
1062+ web_contents->GetPrimaryMainFrame ()->GetStoragePartition ();
1063+ ASSERT_TRUE (storage_partition);
1064+
1065+ content::StoragePartitionConfig default_config =
1066+ content::StoragePartitionConfig::CreateDefault (browser ()->profile ());
1067+
1068+ // The storage partition should be the default one
1069+ EXPECT_EQ (default_config, storage_partition->GetConfig ());
1070+ EXPECT_TRUE (storage_partition->GetConfig ().is_default ());
1071+ EXPECT_EQ (" " , storage_partition->GetConfig ().partition_domain ());
1072+ EXPECT_EQ (" " , storage_partition->GetConfig ().partition_name ());
1073+
1074+ // Verify the restored page behaves like about:blank - it's a valid page
1075+ // but doesn't have access to storage and cookies from the container
1076+ content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame ();
1077+ ASSERT_TRUE (main_frame);
1078+
1079+ // The page is not an error document, but it's essentially blank
1080+ EXPECT_FALSE (main_frame->IsErrorDocument ());
1081+
1082+ // Verify that JavaScript calls to access storage throw exceptions
1083+ // (the page doesn't have a valid document context for storage APIs)
1084+ content::EvalJsResult cookie_result =
1085+ content::EvalJs (web_contents, GetCookiesJS ());
1086+ EXPECT_FALSE (cookie_result.is_ok ())
1087+ << " Expected JS exception when accessing cookies, but got: "
1088+ << cookie_result;
1089+
1090+ content::EvalJsResult local_storage_result =
1091+ content::EvalJs (web_contents, GetLocalStorageJS (" test_key" ));
1092+ EXPECT_FALSE (local_storage_result.is_ok ())
1093+ << " Expected JS exception when accessing localStorage, but got: "
1094+ << local_storage_result;
1095+ }
1096+
8541097} // namespace containers
0 commit comments