| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include <stdint.h> | 5 #include <stdint.h> |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
| 9 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 9 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
| 10 #include "chrome/browser/extensions/browser_action_test_util.h" | 10 #include "chrome/browser/extensions/browser_action_test_util.h" |
| 11 #include "chrome/browser/extensions/extension_action.h" | 11 #include "chrome/browser/extensions/extension_action.h" |
| 12 #include "chrome/browser/extensions/extension_action_icon_factory.h" | 12 #include "chrome/browser/extensions/extension_action_icon_factory.h" |
| 13 #include "chrome/browser/extensions/extension_action_manager.h" | 13 #include "chrome/browser/extensions/extension_action_manager.h" |
| 14 #include "chrome/browser/extensions/extension_action_runner.h" | 14 #include "chrome/browser/extensions/extension_action_runner.h" |
| 15 #include "chrome/browser/extensions/extension_apitest.h" | 15 #include "chrome/browser/extensions/extension_apitest.h" |
| 16 #include "chrome/browser/extensions/extension_tab_util.h" | 16 #include "chrome/browser/extensions/extension_tab_util.h" |
| 17 #include "chrome/browser/extensions/extension_util.h" | 17 #include "chrome/browser/extensions/extension_util.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/browser/ui/browser.h" | 19 #include "chrome/browser/ui/browser.h" |
| 20 #include "chrome/browser/ui/browser_commands.h" | 20 #include "chrome/browser/ui/browser_commands.h" |
| 21 #include "chrome/browser/ui/browser_finder.h" | 21 #include "chrome/browser/ui/browser_finder.h" |
| 22 #include "chrome/browser/ui/browser_navigator_params.h" | 22 #include "chrome/browser/ui/browser_navigator_params.h" |
| 23 #include "chrome/browser/ui/browser_window.h" | 23 #include "chrome/browser/ui/browser_window.h" |
| 24 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 24 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 25 #include "chrome/common/url_constants.h" | 25 #include "chrome/common/url_constants.h" |
| 26 #include "chrome/test/base/ui_test_utils.h" | 26 #include "chrome/test/base/ui_test_utils.h" |
| 27 #include "content/public/browser/browser_context.h" |
| 27 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
| 28 #include "content/public/browser/render_frame_host.h" | 29 #include "content/public/browser/render_frame_host.h" |
| 29 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
| 30 #include "content/public/test/browser_test_utils.h" | 31 #include "content/public/test/browser_test_utils.h" |
| 32 #include "content/public/test/content_browser_test_utils.h" |
| 33 #include "content/public/test/download_test_observer.h" |
| 34 #include "content/public/test/test_utils.h" |
| 31 #include "extensions/browser/extension_registry.h" | 35 #include "extensions/browser/extension_registry.h" |
| 32 #include "extensions/browser/extension_system.h" | 36 #include "extensions/browser/extension_system.h" |
| 33 #include "extensions/browser/notification_types.h" | 37 #include "extensions/browser/notification_types.h" |
| 34 #include "extensions/browser/process_manager.h" | 38 #include "extensions/browser/process_manager.h" |
| 35 #include "extensions/browser/test_extension_registry_observer.h" | 39 #include "extensions/browser/test_extension_registry_observer.h" |
| 36 #include "extensions/common/feature_switch.h" | 40 #include "extensions/common/feature_switch.h" |
| 37 #include "extensions/test/extension_test_message_listener.h" | 41 #include "extensions/test/extension_test_message_listener.h" |
| 38 #include "extensions/test/result_catcher.h" | 42 #include "extensions/test/result_catcher.h" |
| 39 #include "grit/theme_resources.h" | 43 #include "grit/theme_resources.h" |
| 40 #include "net/dns/mock_host_resolver.h" | 44 #include "net/dns/mock_host_resolver.h" |
| 41 #include "net/test/embedded_test_server/embedded_test_server.h" | 45 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 46 #include "testing/gmock/include/gmock/gmock.h" |
| 42 #include "ui/base/resource/resource_bundle.h" | 47 #include "ui/base/resource/resource_bundle.h" |
| 43 #include "ui/gfx/geometry/rect.h" | 48 #include "ui/gfx/geometry/rect.h" |
| 44 #include "ui/gfx/geometry/size.h" | 49 #include "ui/gfx/geometry/size.h" |
| 45 #include "ui/gfx/image/canvas_image_source.h" | 50 #include "ui/gfx/image/canvas_image_source.h" |
| 46 #include "ui/gfx/image/image_skia.h" | 51 #include "ui/gfx/image/image_skia.h" |
| 47 #include "ui/gfx/image/image_skia_operations.h" | 52 #include "ui/gfx/image/image_skia_operations.h" |
| 48 #include "ui/gfx/image/image_unittest_util.h" | 53 #include "ui/gfx/image/image_unittest_util.h" |
| 49 #include "ui/gfx/skia_util.h" | 54 #include "ui/gfx/skia_util.h" |
| 50 | 55 |
| 51 using content::WebContents; | 56 using content::WebContents; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 BrowserActionApiTest() {} | 104 BrowserActionApiTest() {} |
| 100 ~BrowserActionApiTest() override {} | 105 ~BrowserActionApiTest() override {} |
| 101 | 106 |
| 102 protected: | 107 protected: |
| 103 BrowserActionTestUtil* GetBrowserActionsBar() { | 108 BrowserActionTestUtil* GetBrowserActionsBar() { |
| 104 if (!browser_action_test_util_) | 109 if (!browser_action_test_util_) |
| 105 browser_action_test_util_.reset(new BrowserActionTestUtil(browser())); | 110 browser_action_test_util_.reset(new BrowserActionTestUtil(browser())); |
| 106 return browser_action_test_util_.get(); | 111 return browser_action_test_util_.get(); |
| 107 } | 112 } |
| 108 | 113 |
| 109 bool OpenPopup(int index) { | 114 WebContents* OpenPopup(int index) { |
| 110 ResultCatcher catcher; | 115 ResultCatcher catcher; |
| 111 content::WindowedNotificationObserver popup_observer( | 116 content::WindowedNotificationObserver popup_observer( |
| 112 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, | 117 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, |
| 113 content::NotificationService::AllSources()); | 118 content::NotificationService::AllSources()); |
| 114 GetBrowserActionsBar()->Press(index); | 119 GetBrowserActionsBar()->Press(index); |
| 115 popup_observer.Wait(); | 120 popup_observer.Wait(); |
| 116 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | 121 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| 117 return GetBrowserActionsBar()->HasPopup(); | 122 |
| 123 if (!GetBrowserActionsBar()->HasPopup()) |
| 124 return nullptr; |
| 125 |
| 126 const auto& source = static_cast<const content::Source<WebContents>&>( |
| 127 popup_observer.source()); |
| 128 return source.ptr(); |
| 118 } | 129 } |
| 119 | 130 |
| 120 ExtensionAction* GetBrowserAction(const Extension& extension) { | 131 ExtensionAction* GetBrowserAction(const Extension& extension) { |
| 121 return ExtensionActionManager::Get(browser()->profile())-> | 132 return ExtensionActionManager::Get(browser()->profile())-> |
| 122 GetBrowserAction(extension); | 133 GetBrowserAction(extension); |
| 123 } | 134 } |
| 124 | 135 |
| 125 private: | 136 private: |
| 126 std::unique_ptr<BrowserActionTestUtil> browser_action_test_util_; | 137 std::unique_ptr<BrowserActionTestUtil> browser_action_test_util_; |
| 127 | 138 |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 ExtensionTestMessageListener listener("ready", true); | 799 ExtensionTestMessageListener listener("ready", true); |
| 789 EXPECT_TRUE(LoadExtension( | 800 EXPECT_TRUE(LoadExtension( |
| 790 test_data_dir_.AppendASCII("browser_action/open_popup_on_reply"))); | 801 test_data_dir_.AppendASCII("browser_action/open_popup_on_reply"))); |
| 791 EXPECT_TRUE(listener.WaitUntilSatisfied()); | 802 EXPECT_TRUE(listener.WaitUntilSatisfied()); |
| 792 | 803 |
| 793 ResultCatcher catcher; | 804 ResultCatcher catcher; |
| 794 listener.Reply(std::string()); | 805 listener.Reply(std::string()); |
| 795 EXPECT_TRUE(catcher.GetNextResult()) << message_; | 806 EXPECT_TRUE(catcher.GetNextResult()) << message_; |
| 796 } | 807 } |
| 797 | 808 |
| 809 class NavigatingExtensionPopupBrowserTest : public BrowserActionApiTest { |
| 810 public: |
| 811 const Extension& popup_extension() { return *popup_extension_; } |
| 812 const Extension& other_extension() { return *other_extension_; } |
| 813 |
| 814 void SetUpOnMainThread() override { |
| 815 BrowserActionApiTest::SetUpOnMainThread(); |
| 816 |
| 817 host_resolver()->AddRule("*", "127.0.0.1"); |
| 818 ASSERT_TRUE(embedded_test_server()->Start()); |
| 819 |
| 820 // Load an extension with a pop-up. |
| 821 ASSERT_TRUE(popup_extension_ = LoadExtension(test_data_dir_.AppendASCII( |
| 822 "browser_action/popup_with_form"))); |
| 823 |
| 824 // Load another extension (that we can try navigating to). |
| 825 ASSERT_TRUE(other_extension_ = LoadExtension(test_data_dir_.AppendASCII( |
| 826 "browser_action/popup_with_iframe"))); |
| 827 } |
| 828 |
| 829 enum ExpectedNavigationStatus { |
| 830 EXPECTING_NAVIGATION_SUCCESS, |
| 831 EXPECTING_NAVIGATION_FAILURE, |
| 832 }; |
| 833 |
| 834 void TestPopupNavigationViaGet( |
| 835 const GURL& target_url, |
| 836 ExpectedNavigationStatus expected_navigation_status) { |
| 837 std::string navigation_starting_script = |
| 838 "window.location = '" + target_url.spec() + "';\n"; |
| 839 TestPopupNavigation(target_url, expected_navigation_status, |
| 840 navigation_starting_script); |
| 841 } |
| 842 |
| 843 void TestPopupNavigationViaPost( |
| 844 const GURL& target_url, |
| 845 ExpectedNavigationStatus expected_navigation_status) { |
| 846 std::string navigation_starting_script = |
| 847 "var form = document.getElementById('form');\n" |
| 848 "form.action = '" + target_url.spec() + "';\n" |
| 849 "form.submit();\n"; |
| 850 TestPopupNavigation(target_url, expected_navigation_status, |
| 851 navigation_starting_script); |
| 852 } |
| 853 |
| 854 private: |
| 855 void TestPopupNavigation(const GURL& target_url, |
| 856 ExpectedNavigationStatus expected_navigation_status, |
| 857 std::string navigation_starting_script) { |
| 858 // Were there any failures so far (e.g. in SetUpOnMainThread)? |
| 859 ASSERT_FALSE(HasFailure()); |
| 860 |
| 861 // Simulate a click on the browser action to open the popup. |
| 862 WebContents* popup = OpenPopup(0); |
| 863 ASSERT_TRUE(popup); |
| 864 GURL popup_url = popup_extension().GetResourceURL("popup.html"); |
| 865 EXPECT_EQ(popup_url, popup->GetLastCommittedURL()); |
| 866 |
| 867 // Note that the |setTimeout| call below is needed to make sure |
| 868 // ExecuteScriptAndExtractBool returns *after* a scheduled navigation has |
| 869 // already started. |
| 870 std::string script_to_execute = |
| 871 navigation_starting_script + |
| 872 "setTimeout(\n" |
| 873 " function() { window.domAutomationController.send(true); },\n" |
| 874 " 0);\n"; |
| 875 |
| 876 // Try to navigate the pop-up. |
| 877 bool ignored_script_result = false; |
| 878 content::WebContentsDestroyedWatcher popup_destruction_watcher(popup); |
| 879 EXPECT_TRUE(ExecuteScriptAndExtractBool(popup, script_to_execute, |
| 880 &ignored_script_result)); |
| 881 popup = popup_destruction_watcher.web_contents(); |
| 882 |
| 883 // Verify if the popup navigation succeeded or failed as expected. |
| 884 if (!popup) { |
| 885 // If navigation ends up in a tab, then the tab will be focused and |
| 886 // therefore the popup will be closed, destroying associated WebContents - |
| 887 // don't do any verification in this case. |
| 888 ADD_FAILURE() << "Navigation should not close extension pop-up"; |
| 889 } else { |
| 890 // If the extension popup is still opened, then wait until there is no |
| 891 // load in progress, and verify whether the navigation succeeded or not. |
| 892 WaitForLoadStop(popup); |
| 893 if (expected_navigation_status == EXPECTING_NAVIGATION_SUCCESS) { |
| 894 EXPECT_EQ(target_url, popup->GetLastCommittedURL()) |
| 895 << "Navigation to " << target_url |
| 896 << " should succeed in an extension pop-up"; |
| 897 } else { |
| 898 EXPECT_NE(target_url, popup->GetLastCommittedURL()) |
| 899 << "Navigation to " << target_url |
| 900 << " should fail in an extension pop-up"; |
| 901 EXPECT_THAT( |
| 902 popup->GetLastCommittedURL(), |
| 903 ::testing::AnyOf(::testing::Eq(popup_url), |
| 904 ::testing::Eq(GURL("chrome-extension://invalid")), |
| 905 ::testing::Eq(GURL("about:blank")))); |
| 906 } |
| 907 |
| 908 // Close the pop-up. |
| 909 EXPECT_TRUE(GetBrowserActionsBar()->HidePopup()); |
| 910 popup_destruction_watcher.Wait(); |
| 911 } |
| 912 |
| 913 // Make sure that the web navigation did not succeed somewhere outside of |
| 914 // the extension popup (as it might if ExtensionViewHost::OpenURLFromTab |
| 915 // forwards the navigation to Browser::OpenURL [which doesn't specify a |
| 916 // source WebContents]). |
| 917 TabStripModel* tabs = browser()->tab_strip_model(); |
| 918 for (int i = 0; i < tabs->count(); i++) { |
| 919 WebContents* tab_contents = tabs->GetWebContentsAt(i); |
| 920 WaitForLoadStop(tab_contents); |
| 921 EXPECT_NE(target_url, tab_contents->GetLastCommittedURL()) |
| 922 << "Navigating an extension pop-up should not affect tabs."; |
| 923 } |
| 924 } |
| 925 |
| 926 const Extension* popup_extension_; |
| 927 const Extension* other_extension_; |
| 928 }; |
| 929 |
| 930 // Tests that an extension pop-up cannot be navigated to a web page. |
| 931 IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, Webpage) { |
| 932 GURL web_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); |
| 933 TestPopupNavigationViaGet(web_url, EXPECTING_NAVIGATION_FAILURE); |
| 934 TestPopupNavigationViaPost(web_url, EXPECTING_NAVIGATION_FAILURE); |
| 935 } |
| 936 |
| 937 // Tests that an extension pop-up can be navigated to another page |
| 938 // in the same extension. |
| 939 IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, |
| 940 PageInSameExtension) { |
| 941 GURL other_page_in_same_extension = |
| 942 popup_extension().GetResourceURL("other_page.html"); |
| 943 TestPopupNavigationViaGet(other_page_in_same_extension, |
| 944 EXPECTING_NAVIGATION_SUCCESS); |
| 945 TestPopupNavigationViaPost(other_page_in_same_extension, |
| 946 EXPECTING_NAVIGATION_SUCCESS); |
| 947 } |
| 948 |
| 949 // Tests that an extension pop-up cannot be navigated to a page |
| 950 // in another extension. |
| 951 IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, |
| 952 PageInOtherExtension) { |
| 953 GURL other_extension_url = other_extension().GetResourceURL("other.html"); |
| 954 TestPopupNavigationViaGet(other_extension_url, EXPECTING_NAVIGATION_FAILURE); |
| 955 TestPopupNavigationViaPost(other_extension_url, EXPECTING_NAVIGATION_FAILURE); |
| 956 } |
| 957 |
| 958 // Tests that navigating an extension pop-up to a http URI that returns |
| 959 // Content-Disposition: attachment; filename=... |
| 960 // works: No navigation, but download shelf visible + download goes through. |
| 961 // |
| 962 // Note - there is no "...ViaGet" flavour of this test, because we don't care |
| 963 // (yet) if GET succeeds with the download or not (it probably should succeed |
| 964 // for consistency with POST, but it always failed in M54 and before). After |
| 965 // abandoing ShouldFork/OpenURL for all methods (not just for POST) [see comment |
| 966 // about https://crbug.com/646261 in ChromeContentRendererClient::ShouldFork] |
| 967 // GET should automagically start working for downloads. |
| 968 // TODO(lukasza): https://crbug.com/650694: Add a "Get" flavour of the test once |
| 969 // the download works both for GET and POST requests. |
| 970 IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, DownloadViaPost) { |
| 971 content::DownloadTestObserverTerminal downloads_observer( |
| 972 content::BrowserContext::GetDownloadManager(browser()->profile()), |
| 973 1, // == wait_count (only waiting for "download-test3.gif"). |
| 974 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); |
| 975 |
| 976 // Navigate to a URL that replies with |
| 977 // Content-Disposition: attachment; filename=... |
| 978 // header. |
| 979 GURL download_url( |
| 980 embedded_test_server()->GetURL("foo.com", "/download-test3.gif")); |
| 981 TestPopupNavigationViaPost(download_url, EXPECTING_NAVIGATION_FAILURE); |
| 982 |
| 983 // Verify that "download-test3.gif got downloaded. |
| 984 downloads_observer.WaitForFinished(); |
| 985 EXPECT_EQ(0u, downloads_observer.NumDangerousDownloadsSeen()); |
| 986 EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState( |
| 987 content::DownloadItem::COMPLETE)); |
| 988 |
| 989 // The test verification below is applicable only to scenarios where the |
| 990 // download shelf is supported - on ChromeOS, instead of the download shelf, |
| 991 // there is a download notification in the right-bottom corner of the screen. |
| 992 #if !defined(OS_CHROMEOS) |
| 993 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible()); |
| 994 #endif |
| 995 } |
| 996 |
| 798 } // namespace | 997 } // namespace |
| 799 } // namespace extensions | 998 } // namespace extensions |
| OLD | NEW |