| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file tests that Service Workers (a Content feature) work in the Chromium | 5 // This file tests that Service Workers (a Content feature) work in the Chromium |
| 6 // embedder. | 6 // embedder. |
| 7 | 7 |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/numerics/safe_conversions.h" | 11 #include "base/numerics/safe_conversions.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/test/histogram_tester.h" |
| 15 #include "base/threading/thread_restrictions.h" | 16 #include "base/threading/thread_restrictions.h" |
| 16 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 17 #include "chrome/browser/chrome_notification_types.h" | 18 #include "chrome/browser/chrome_notification_types.h" |
| 18 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 19 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 19 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 20 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
| 21 #include "chrome/browser/net/prediction_options.h" |
| 22 #include "chrome/browser/net/predictor.h" |
| 20 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/browser/ui/browser.h" | 24 #include "chrome/browser/ui/browser.h" |
| 22 #include "chrome/browser/ui/browser_window.h" | 25 #include "chrome/browser/ui/browser_window.h" |
| 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 24 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/test/base/in_process_browser_test.h" | 28 #include "chrome/test/base/in_process_browser_test.h" |
| 26 #include "chrome/test/base/ui_test_utils.h" | 29 #include "chrome/test/base/ui_test_utils.h" |
| 27 #include "components/content_settings/core/browser/host_content_settings_map.h" | 30 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 28 #include "content/public/browser/browser_context.h" | 31 #include "content/public/browser/browser_context.h" |
| 29 #include "content/public/browser/render_frame_host.h" | 32 #include "content/public/browser/render_frame_host.h" |
| 30 #include "content/public/browser/service_worker_context.h" | 33 #include "content/public/browser/service_worker_context.h" |
| 31 #include "content/public/browser/storage_partition.h" | 34 #include "content/public/browser/storage_partition.h" |
| 32 #include "content/public/browser/web_contents.h" | 35 #include "content/public/browser/web_contents.h" |
| 33 #include "content/public/test/browser_test_utils.h" | 36 #include "content/public/test/browser_test_utils.h" |
| 34 #include "net/test/embedded_test_server/embedded_test_server.h" | 37 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 38 #include "net/test/embedded_test_server/embedded_test_server_connection_listener
.h" |
| 35 #include "ppapi/shared_impl/ppapi_switches.h" | 39 #include "ppapi/shared_impl/ppapi_switches.h" |
| 36 | 40 |
| 37 namespace { | 41 namespace { |
| 38 | 42 |
| 39 class ChromeServiceWorkerTest : public InProcessBrowserTest { | 43 class ChromeServiceWorkerTest : public InProcessBrowserTest { |
| 40 protected: | 44 protected: |
| 41 ChromeServiceWorkerTest() { | 45 ChromeServiceWorkerTest() { |
| 42 EXPECT_TRUE(service_worker_dir_.CreateUniqueTempDir()); | 46 EXPECT_TRUE(service_worker_dir_.CreateUniqueTempDir()); |
| 43 EXPECT_TRUE(base::CreateDirectoryAndGetError( | 47 EXPECT_TRUE(base::CreateDirectoryAndGetError( |
| 44 service_worker_dir_.GetPath().Append( | 48 service_worker_dir_.GetPath().Append( |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 EXPECT_EQ(GetRequestStringForPNACL("#OtherCredentials"), | 608 EXPECT_EQ(GetRequestStringForPNACL("#OtherCredentials"), |
| 605 ExecutePNACLUrlLoaderTest("OtherCredentials")); | 609 ExecutePNACLUrlLoaderTest("OtherCredentials")); |
| 606 } | 610 } |
| 607 | 611 |
| 608 IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerFetchPPAPIPrivateTest, | 612 IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerFetchPPAPIPrivateTest, |
| 609 OtherOriginCORSCredentials) { | 613 OtherOriginCORSCredentials) { |
| 610 EXPECT_EQ(GetRequestStringForPNACL("#OtherCORSCredentials"), | 614 EXPECT_EQ(GetRequestStringForPNACL("#OtherCORSCredentials"), |
| 611 ExecutePNACLUrlLoaderTest("OtherCORSCredentials")); | 615 ExecutePNACLUrlLoaderTest("OtherCORSCredentials")); |
| 612 } | 616 } |
| 613 | 617 |
| 618 class ConnectionListener |
| 619 : public net::test_server::EmbeddedTestServerConnectionListener { |
| 620 public: |
| 621 ConnectionListener() : task_runner_(base::ThreadTaskRunnerHandle::Get()) {} |
| 622 ~ConnectionListener() override {} |
| 623 |
| 624 void AcceptedSocket(const net::StreamSocket& connection) override { |
| 625 base::AutoLock lock(lock_); |
| 626 socket_accepted_ = true; |
| 627 if (wait_accept_loop_) |
| 628 task_runner_->PostTask(FROM_HERE, wait_accept_loop_->QuitClosure()); |
| 629 } |
| 630 void ReadFromSocket(const net::StreamSocket& socket, int rv) override {} |
| 631 |
| 632 void ResetSocketAcceptedFlag() { |
| 633 base::AutoLock lock(lock_); |
| 634 socket_accepted_ = false; |
| 635 } |
| 636 |
| 637 bool GetSocketAcceptedFlag() const { |
| 638 base::AutoLock lock(lock_); |
| 639 return socket_accepted_; |
| 640 } |
| 641 |
| 642 void WaitForSocketAcceptedOnUI() { |
| 643 { |
| 644 base::AutoLock lock(lock_); |
| 645 if (socket_accepted_) |
| 646 return; |
| 647 wait_accept_loop_.reset(new base::RunLoop()); |
| 648 } |
| 649 wait_accept_loop_->Run(); |
| 650 } |
| 651 |
| 652 private: |
| 653 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 654 |
| 655 // This lock protects the members below, which each are used on both the |
| 656 // IO and UI thread. Members declared after the lock are protected by it. |
| 657 mutable base::Lock lock_; |
| 658 bool socket_accepted_ = false; |
| 659 std::unique_ptr<base::RunLoop> wait_accept_loop_; |
| 660 |
| 661 DISALLOW_COPY_AND_ASSIGN(ConnectionListener); |
| 662 }; |
| 663 |
| 664 class ChromeServiceWorkerPredictionOptionsTest |
| 665 : public ChromeServiceWorkerTest, |
| 666 public ::testing::WithParamInterface< |
| 667 chrome_browser_net::NetworkPredictionOptionsForServiceWorker> { |
| 668 protected: |
| 669 ChromeServiceWorkerPredictionOptionsTest() |
| 670 : cross_site_test_server_(new net::EmbeddedTestServer()) {} |
| 671 ~ChromeServiceWorkerPredictionOptionsTest() override {} |
| 672 |
| 673 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 674 ChromeServiceWorkerTest::SetUpCommandLine(command_line); |
| 675 switch (GetParam()) { |
| 676 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 677 PRECONNECT_ONLY: |
| 678 command_line->AppendSwitchASCII( |
| 679 switches::kNetworkPredictionOptionsForServiceWorker, |
| 680 chrome_browser_net::kPreconnectOnly); |
| 681 break; |
| 682 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 683 START_SERVICE_WORKER_AND_PRECONNECT: |
| 684 command_line->AppendSwitchASCII( |
| 685 switches::kNetworkPredictionOptionsForServiceWorker, |
| 686 chrome_browser_net::kStartServiceWorkerAndPreconnect); |
| 687 break; |
| 688 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 689 START_SERVICE_WORKER_AND_DEFER_PRECONNECT: |
| 690 command_line->AppendSwitchASCII( |
| 691 switches::kNetworkPredictionOptionsForServiceWorker, |
| 692 chrome_browser_net::kStartServiceWorkerAndDeferPreconnect); |
| 693 break; |
| 694 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 695 START_SERVICE_WORKER_ONLY: |
| 696 command_line->AppendSwitchASCII( |
| 697 switches::kNetworkPredictionOptionsForServiceWorker, |
| 698 chrome_browser_net::kStartServiceWorkerOnly); |
| 699 break; |
| 700 } |
| 701 } |
| 702 |
| 703 void SetUpOnMainThread() override { |
| 704 WriteServiceWorkerPredictionOptionsTestFiles(); |
| 705 |
| 706 embedded_test_server()->ServeFilesFromDirectory( |
| 707 service_worker_dir_.GetPath()); |
| 708 ASSERT_TRUE(embedded_test_server()->Start()); |
| 709 |
| 710 cross_site_test_server()->ServeFilesFromDirectory( |
| 711 service_worker_dir_.GetPath()); |
| 712 cross_site_connection_listener_.reset(new ConnectionListener()); |
| 713 cross_site_test_server()->SetConnectionListener( |
| 714 cross_site_connection_listener_.get()); |
| 715 ASSERT_TRUE(cross_site_test_server()->Start()); |
| 716 |
| 717 browser()->profile()->GetNetworkPredictor()->SetPredictorEnabledForTest( |
| 718 true); |
| 719 } |
| 720 |
| 721 void InitializeServiceWorkerTest() { |
| 722 base::HistogramTester histogram_tester; |
| 723 const base::string16 expected_title = base::ASCIIToUTF16("READY"); |
| 724 content::TitleWatcher title_watcher( |
| 725 browser()->tab_strip_model()->GetActiveWebContents(), expected_title); |
| 726 ui_test_utils::NavigateToURL( |
| 727 browser(), embedded_test_server()->GetURL( |
| 728 "/sw_test_page.html?" + |
| 729 cross_site_test_server()->GetURL("/test.js").spec())); |
| 730 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 731 histogram_tester.ExpectTotalCount("ServiceWorker.StartNewWorker.Status", 1); |
| 732 histogram_tester.ExpectBucketCount("ServiceWorker.StartNewWorker.Status", |
| 733 0 /* SERVICE_WORKER_OK */, 1); |
| 734 |
| 735 // Stop the service worker. |
| 736 content::BrowserContext::GetDefaultStoragePartition(browser()->profile()) |
| 737 ->GetServiceWorkerContext() |
| 738 ->StopAllServiceWorkersForOrigin(embedded_test_server()->base_url()); |
| 739 |
| 740 // Disconnect the connection. |
| 741 cross_site_test_server()->FlushAllSocketsAndConnectionsOnUIThread(); |
| 742 EXPECT_TRUE(cross_site_connection_listener()->GetSocketAcceptedFlag()); |
| 743 cross_site_connection_listener()->ResetSocketAcceptedFlag(); |
| 744 } |
| 745 |
| 746 void NavigateToServiceWorkerTestPage() { |
| 747 const base::string16 expected_title = base::ASCIIToUTF16("SW"); |
| 748 content::TitleWatcher title_watcher( |
| 749 browser()->tab_strip_model()->GetActiveWebContents(), expected_title); |
| 750 ui_test_utils::NavigateToURL(browser(), |
| 751 embedded_test_server()->GetURL("/dummy.html")); |
| 752 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 753 } |
| 754 |
| 755 void InitializeNoServiceWorkerTest() { |
| 756 const base::string16 expected_title = base::ASCIIToUTF16("READY"); |
| 757 content::TitleWatcher title_watcher( |
| 758 browser()->tab_strip_model()->GetActiveWebContents(), expected_title); |
| 759 ui_test_utils::NavigateToURL( |
| 760 browser(), embedded_test_server()->GetURL( |
| 761 "/no_sw_test_page.html?" + |
| 762 cross_site_test_server()->GetURL("/test.js").spec())); |
| 763 |
| 764 // Disconnect the connection. |
| 765 cross_site_test_server()->FlushAllSocketsAndConnectionsOnUIThread(); |
| 766 EXPECT_TRUE(cross_site_connection_listener()->GetSocketAcceptedFlag()); |
| 767 cross_site_connection_listener()->ResetSocketAcceptedFlag(); |
| 768 } |
| 769 |
| 770 void NavigateToNoServiceWorkerTestPage() { |
| 771 const base::string16 expected_title = base::ASCIIToUTF16("READY"); |
| 772 content::TitleWatcher title_watcher( |
| 773 browser()->tab_strip_model()->GetActiveWebContents(), expected_title); |
| 774 ui_test_utils::NavigateToURL( |
| 775 browser(), embedded_test_server()->GetURL("/no_sw_test_page.html")); |
| 776 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 777 } |
| 778 |
| 779 net::EmbeddedTestServer* cross_site_test_server() { |
| 780 return cross_site_test_server_.get(); |
| 781 } |
| 782 |
| 783 ConnectionListener* cross_site_connection_listener() { |
| 784 return cross_site_connection_listener_.get(); |
| 785 } |
| 786 |
| 787 private: |
| 788 void WriteServiceWorkerPredictionOptionsTestFiles() { |
| 789 WriteFile(FILE_PATH_LITERAL("test.js"), "document.title = 'READY';"); |
| 790 WriteFile(FILE_PATH_LITERAL("sw.js"), |
| 791 "this.onfetch = function(event) {" |
| 792 " event.respondWith(new Response(" |
| 793 " '<title>SW</title>', " |
| 794 " {headers: {'Content-Type': 'text/html'}}));" |
| 795 "};"); |
| 796 WriteFile(FILE_PATH_LITERAL("sw_test_page.html"), |
| 797 "<body><script>" |
| 798 "navigator.serviceWorker.register('./sw.js', {scope: './'})" |
| 799 " .then(reg => {" |
| 800 " reg.addEventListener('updatefound', _ => {" |
| 801 " var worker = reg.installing;" |
| 802 " worker.addEventListener('statechange', _ => {" |
| 803 " if (worker.state != 'activated')" |
| 804 " return;" |
| 805 " var script = document.createElement('script');" |
| 806 " script.src = window.location.search.substring(1);" |
| 807 " document.body.appendChild(script);" |
| 808 " });" |
| 809 " });" |
| 810 " });" |
| 811 "</script></body>"); |
| 812 WriteFile(FILE_PATH_LITERAL("no_sw_test_page.html"), |
| 813 "<body><script>" |
| 814 "if (window.location.search != '') {" |
| 815 " var script = document.createElement('script');" |
| 816 " script.src = window.location.search.substring(1);" |
| 817 " document.body.appendChild(script);" |
| 818 "} else {" |
| 819 " document.title = 'READY';" |
| 820 "}" |
| 821 "</script></body>"); |
| 822 } |
| 823 |
| 824 std::unique_ptr<net::EmbeddedTestServer> cross_site_test_server_; |
| 825 std::unique_ptr<ConnectionListener> cross_site_connection_listener_; |
| 826 |
| 827 DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerPredictionOptionsTest); |
| 828 }; |
| 829 |
| 830 IN_PROC_BROWSER_TEST_P(ChromeServiceWorkerPredictionOptionsTest, |
| 831 ServiceWorkerTest) { |
| 832 InitializeServiceWorkerTest(); |
| 833 base::HistogramTester histogram_tester; |
| 834 NavigateToServiceWorkerTestPage(); |
| 835 histogram_tester.ExpectTotalCount("ServiceWorker.StartWorker.Purpose", 1); |
| 836 |
| 837 switch (GetParam()) { |
| 838 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 839 PRECONNECT_ONLY: |
| 840 histogram_tester.ExpectBucketCount( |
| 841 "ServiceWorker.StartWorker.Purpose", |
| 842 10 /* ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME */, 1); |
| 843 break; |
| 844 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 845 START_SERVICE_WORKER_AND_PRECONNECT: |
| 846 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 847 START_SERVICE_WORKER_AND_DEFER_PRECONNECT: |
| 848 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 849 START_SERVICE_WORKER_ONLY: |
| 850 histogram_tester.ExpectBucketCount( |
| 851 "ServiceWorker.StartWorker.Purpose", |
| 852 27 /* ServiceWorkerMetrics::EventType::PRECONNECT */, 1); |
| 853 break; |
| 854 } |
| 855 |
| 856 // Note: Wrting a chrome browset test which checks that the preconnection is |
| 857 // defered until the service worker startup is too complex. So we only check |
| 858 // that the preconnection is accutualy executed. |
| 859 switch (GetParam()) { |
| 860 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 861 PRECONNECT_ONLY: |
| 862 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 863 START_SERVICE_WORKER_AND_PRECONNECT: |
| 864 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 865 START_SERVICE_WORKER_AND_DEFER_PRECONNECT: |
| 866 cross_site_connection_listener()->WaitForSocketAcceptedOnUI(); |
| 867 break; |
| 868 case chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 869 START_SERVICE_WORKER_ONLY: |
| 870 EXPECT_FALSE(cross_site_connection_listener()->GetSocketAcceptedFlag()); |
| 871 break; |
| 872 } |
| 873 } |
| 874 |
| 875 IN_PROC_BROWSER_TEST_P(ChromeServiceWorkerPredictionOptionsTest, |
| 876 NoServiceWorkerTest) { |
| 877 InitializeNoServiceWorkerTest(); |
| 878 base::HistogramTester histogram_tester; |
| 879 NavigateToNoServiceWorkerTestPage(); |
| 880 // If there is no service workers, the preconnection must be executed |
| 881 // regardless of the options. |
| 882 cross_site_connection_listener()->WaitForSocketAcceptedOnUI(); |
| 883 } |
| 884 |
| 885 INSTANTIATE_TEST_CASE_P( |
| 886 /* no prefix */, |
| 887 ChromeServiceWorkerPredictionOptionsTest, |
| 888 ::testing::Values( |
| 889 chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 890 PRECONNECT_ONLY, |
| 891 chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 892 START_SERVICE_WORKER_AND_PRECONNECT, |
| 893 chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 894 START_SERVICE_WORKER_AND_DEFER_PRECONNECT, |
| 895 chrome_browser_net::NetworkPredictionOptionsForServiceWorker:: |
| 896 START_SERVICE_WORKER_ONLY)); |
| 897 |
| 614 } // namespace | 898 } // namespace |
| OLD | NEW |