Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Side by Side Diff: chrome/browser/extensions/api/extension_action/browser_action_apitest.cc

Issue 2380193003: Block navigations in extensions via ShouldTransferNavigation (not via OpenURL). (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/extensions/extension_view_host.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/extensions/extension_view_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698