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 "base/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/macros.h" | 6 #include "base/macros.h" |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/optional.h" | 8 #include "base/optional.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
13 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
14 #include "chrome/browser/extensions/active_tab_permission_granter.h" | 14 #include "chrome/browser/extensions/active_tab_permission_granter.h" |
15 #include "chrome/browser/extensions/extension_action_runner.h" | 15 #include "chrome/browser/extensions/extension_action_runner.h" |
16 #include "chrome/browser/extensions/extension_apitest.h" | 16 #include "chrome/browser/extensions/extension_apitest.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/extension_with_management_policy_apitest.h" |
18 #include "chrome/browser/extensions/tab_helper.h" | 19 #include "chrome/browser/extensions/tab_helper.h" |
19 #include "chrome/browser/extensions/test_extension_dir.h" | 20 #include "chrome/browser/extensions/test_extension_dir.h" |
20 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
21 #include "chrome/browser/search_engines/template_url_service_factory.h" | 22 #include "chrome/browser/search_engines/template_url_service_factory.h" |
22 #include "chrome/browser/ui/browser.h" | 23 #include "chrome/browser/ui/browser.h" |
23 #include "chrome/browser/ui/browser_navigator_params.h" | 24 #include "chrome/browser/ui/browser_navigator_params.h" |
24 #include "chrome/browser/ui/login/login_handler.h" | 25 #include "chrome/browser/ui/login/login_handler.h" |
25 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
26 #include "chrome/common/extensions/extension_process_policy.h" | 27 #include "chrome/common/extensions/extension_process_policy.h" |
27 #include "chrome/test/base/search_test_utils.h" | 28 #include "chrome/test/base/search_test_utils.h" |
(...skipping 11 matching lines...) Expand all Loading... |
39 #include "content/public/test/browser_test_utils.h" | 40 #include "content/public/test/browser_test_utils.h" |
40 #include "extensions/browser/api/web_request/web_request_api.h" | 41 #include "extensions/browser/api/web_request/web_request_api.h" |
41 #include "extensions/browser/blocked_action_type.h" | 42 #include "extensions/browser/blocked_action_type.h" |
42 #include "extensions/browser/extension_system.h" | 43 #include "extensions/browser/extension_system.h" |
43 #include "extensions/common/extension_builder.h" | 44 #include "extensions/common/extension_builder.h" |
44 #include "extensions/common/features/feature.h" | 45 #include "extensions/common/features/feature.h" |
45 #include "extensions/test/extension_test_message_listener.h" | 46 #include "extensions/test/extension_test_message_listener.h" |
46 #include "extensions/test/result_catcher.h" | 47 #include "extensions/test/result_catcher.h" |
47 #include "net/dns/mock_host_resolver.h" | 48 #include "net/dns/mock_host_resolver.h" |
48 #include "net/test/embedded_test_server/embedded_test_server.h" | 49 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 50 #include "net/test/embedded_test_server/http_request.h" |
49 #include "net/test/test_data_directory.h" | 51 #include "net/test/test_data_directory.h" |
50 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" | 52 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
51 #include "net/url_request/test_url_fetcher_factory.h" | 53 #include "net/url_request/test_url_fetcher_factory.h" |
52 #include "net/url_request/url_fetcher.h" | 54 #include "net/url_request/url_fetcher.h" |
53 #include "net/url_request/url_fetcher_delegate.h" | 55 #include "net/url_request/url_fetcher_delegate.h" |
54 #include "net/url_request/url_request_context_getter.h" | 56 #include "net/url_request/url_request_context_getter.h" |
55 #include "third_party/WebKit/public/platform/WebInputEvent.h" | 57 #include "third_party/WebKit/public/platform/WebInputEvent.h" |
56 | 58 |
57 #if defined(OS_CHROMEOS) | 59 #if defined(OS_CHROMEOS) |
58 #include "chromeos/login/login_state.h" | 60 #include "chromeos/login/login_state.h" |
(...skipping 19 matching lines...) Expand all Loading... |
78 const content::NotificationSource& source, | 80 const content::NotificationSource& source, |
79 const content::NotificationDetails& details) override { | 81 const content::NotificationDetails& details) override { |
80 LoginHandler* handler = | 82 LoginHandler* handler = |
81 content::Details<LoginNotificationDetails>(details).ptr()->handler(); | 83 content::Details<LoginNotificationDetails>(details).ptr()->handler(); |
82 handler->CancelAuth(); | 84 handler->CancelAuth(); |
83 } | 85 } |
84 | 86 |
85 private: | 87 private: |
86 content::NotificationRegistrar registrar_; | 88 content::NotificationRegistrar registrar_; |
87 | 89 |
88 DISALLOW_COPY_AND_ASSIGN(CancelLoginDialog); | 90 DISALLOW_COPY_AND_ASSIGN(CancelLoginDialog); |
89 }; | 91 }; |
90 | 92 |
91 // Sends an XHR request to the provided host, port, and path, and responds when | 93 // Sends an XHR request to the provided host, port, and path, and responds when |
92 // the request was sent. | 94 // the request was sent. |
93 const char kPerformXhrJs[] = | 95 const char kPerformXhrJs[] = |
94 "var url = 'http://%s:%d/%s';\n" | 96 "var url = 'http://%s:%d/%s';\n" |
95 "var xhr = new XMLHttpRequest();\n" | 97 "var xhr = new XMLHttpRequest();\n" |
96 "xhr.open('GET', url);\n" | 98 "xhr.open('GET', url);\n" |
97 "xhr.onload = function() {\n" | 99 "xhr.onload = function() {\n" |
98 " window.domAutomationController.send(true);\n" | 100 " window.domAutomationController.send(true);\n" |
99 "};\n" | 101 "};\n" |
100 "xhr.onerror = function() {\n" | 102 "xhr.onerror = function() {\n" |
101 " window.domAutomationController.send(false);\n" | 103 " window.domAutomationController.send(false);\n" |
102 "};\n" | 104 "};\n" |
103 "xhr.send();\n"; | 105 "xhr.send();\n"; |
104 | 106 |
105 // Performs an XHR in the given |frame|, replying when complete. | 107 // Performs an XHR in the given |frame|, replying when complete. |
106 void PerformXhrInFrame(content::RenderFrameHost* frame, | 108 void PerformXhrInFrame(content::RenderFrameHost* frame, |
107 const std::string& host, | 109 const std::string& host, |
108 int port, | 110 int port, |
109 const std::string& page) { | 111 const std::string& page) { |
110 bool success = false; | 112 bool success = false; |
111 EXPECT_TRUE(ExecuteScriptAndExtractBool( | 113 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
112 frame, | 114 frame, |
113 base::StringPrintf(kPerformXhrJs, host.c_str(), port, page.c_str()), | 115 base::StringPrintf(kPerformXhrJs, host.c_str(), port, page.c_str()), |
114 &success)); | 116 &success)); |
115 EXPECT_TRUE(success); | 117 EXPECT_TRUE(success); |
116 } | 118 } |
117 | 119 |
118 // Returns the current count of webRequests received by the |extension| in | 120 // Returns the current count of a variable stored in the |extension| background |
119 // the background page (assumes the extension stores a value on the window | 121 // page. Returns -1 if something goes awry. |
120 // object). Returns -1 if something goes awry. | 122 int GetCountFromBackgroundPage(const Extension* extension, |
121 int GetWebRequestCountFromBackgroundPage(const Extension* extension, | 123 content::BrowserContext* context, |
122 content::BrowserContext* context) { | 124 const std::string& variable_name) { |
123 ExtensionHost* host = | 125 ExtensionHost* host = |
124 ProcessManager::Get(context)->GetBackgroundHostForExtension( | 126 ProcessManager::Get(context)->GetBackgroundHostForExtension( |
125 extension->id()); | 127 extension->id()); |
126 if (!host || !host->host_contents()) | 128 if (!host || !host->host_contents()) |
127 return -1; | 129 return -1; |
128 | 130 |
129 int count = -1; | 131 int count = -1; |
130 if (!ExecuteScriptAndExtractInt( | 132 if (!ExecuteScriptAndExtractInt( |
131 host->host_contents(), | 133 host->host_contents(), |
132 "window.domAutomationController.send(window.webRequestCount)", | 134 "window.domAutomationController.send(" + variable_name + ")", &count)) |
133 &count)) | |
134 return -1; | 135 return -1; |
135 return count; | 136 return count; |
136 } | 137 } |
137 | 138 |
| 139 // Returns the current count of webRequests received by the |extension| in |
| 140 // the background page (assumes the extension stores a value on the window |
| 141 // object). Returns -1 if something goes awry. |
| 142 int GetWebRequestCountFromBackgroundPage(const Extension* extension, |
| 143 content::BrowserContext* context) { |
| 144 return GetCountFromBackgroundPage(extension, context, |
| 145 "window.webRequestCount"); |
| 146 } |
| 147 |
138 // A test delegate to wait allow waiting for responses to complete with an | 148 // A test delegate to wait allow waiting for responses to complete with an |
139 // expected status and given content. | 149 // expected status and given content. |
140 // TODO(devlin): Other similar classes exist elsewhere. Pull this into a common | 150 // TODO(devlin): Other similar classes exist elsewhere. Pull this into a common |
141 // test class. | 151 // test class. |
142 class TestURLFetcherDelegate : public net::URLFetcherDelegate { | 152 class TestURLFetcherDelegate : public net::URLFetcherDelegate { |
143 public: | 153 public: |
144 // Creating the TestURLFetcherDelegate automatically creates and starts a | 154 // Creating the TestURLFetcherDelegate automatically creates and starts a |
145 // URLFetcher. | 155 // URLFetcher. |
146 TestURLFetcherDelegate( | 156 TestURLFetcherDelegate( |
147 scoped_refptr<net::URLRequestContextGetter> context_getter, | 157 scoped_refptr<net::URLRequestContextGetter> context_getter, |
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 // example.com should also succeed, since it's not through the profile's | 957 // example.com should also succeed, since it's not through the profile's |
948 // request context. | 958 // request context. |
949 SCOPED_TRACE("example.com with System's request context"); | 959 SCOPED_TRACE("example.com with System's request context"); |
950 TestURLFetcherDelegate url_fetcher(system_context, example_url, | 960 TestURLFetcherDelegate url_fetcher(system_context, example_url, |
951 net::URLRequestStatus()); | 961 net::URLRequestStatus()); |
952 url_fetcher.SetExpectedResponse(kExampleFullContent); | 962 url_fetcher.SetExpectedResponse(kExampleFullContent); |
953 url_fetcher.WaitForCompletion(); | 963 url_fetcher.WaitForCompletion(); |
954 } | 964 } |
955 } | 965 } |
956 | 966 |
| 967 // Tests that the webRequest events aren't dispatched when the request initiator |
| 968 // is protected by policy. |
| 969 IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, |
| 970 InitiatorProtectedByPolicy) { |
| 971 // We expect that no request will be hidden or modification blocked. This |
| 972 // means that the request to example.com will be seen by the extension. |
| 973 { |
| 974 ExtensionManagementPolicyUpdater pref(&policy_provider_); |
| 975 pref.AddRuntimeBlockedHost("*", "*://notexample.com"); |
| 976 } |
| 977 |
| 978 ASSERT_TRUE(StartEmbeddedTestServer()); |
| 979 |
| 980 // Host navigated to. |
| 981 const std::string example_com = "example.com"; |
| 982 |
| 983 // URL of a page that initiates a cross domain requests when navigated to. |
| 984 const GURL extension_test_url = embedded_test_server()->GetURL( |
| 985 example_com, |
| 986 "/extensions/api_test/webrequest/policy_blocked/ref_remote_js.html"); |
| 987 |
| 988 ExtensionTestMessageListener listener("ready", false); |
| 989 const Extension* extension = |
| 990 LoadExtension(test_data_dir_.AppendASCII("webrequest/policy_blocked")); |
| 991 ASSERT_TRUE(extension) << message_; |
| 992 EXPECT_TRUE(listener.WaitUntilSatisfied()); |
| 993 |
| 994 // Extension communicates back using this listener name. |
| 995 const std::string listener_message = "protected_origin"; |
| 996 |
| 997 // The number of requests initiated by a protected origin is tracked in |
| 998 // the extension's background page under this variable name. |
| 999 const std::string request_counter_name = "window.protectedOriginCount"; |
| 1000 |
| 1001 EXPECT_EQ(0, GetCountFromBackgroundPage(extension, profile(), |
| 1002 request_counter_name)); |
| 1003 |
| 1004 // Wait until all remote Javascript files have been blocked / pulled down. |
| 1005 ui_test_utils::NavigateToURLWithDisposition( |
| 1006 browser(), extension_test_url, WindowOpenDisposition::CURRENT_TAB, |
| 1007 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 1008 |
| 1009 // Domain that hosts javascript file referenced by example_com. |
| 1010 const std::string example2_com = "example2.com"; |
| 1011 |
| 1012 // The server saw a request for the remote Javascript file. |
| 1013 EXPECT_TRUE(BrowsedTo(example2_com)); |
| 1014 |
| 1015 // The request was seen by the extension. |
| 1016 EXPECT_EQ(1, GetCountFromBackgroundPage(extension, profile(), |
| 1017 request_counter_name)); |
| 1018 |
| 1019 // Clear the list of domains the server has seen. |
| 1020 ClearRequestLog(); |
| 1021 |
| 1022 // Make sure we've cleared the embedded server history. |
| 1023 EXPECT_FALSE(BrowsedTo(example2_com)); |
| 1024 |
| 1025 // Set the policy to hide requests to example.com or any resource |
| 1026 // it includes. We expect that in this test, the request to example2.com |
| 1027 // will not be seen by the extension. |
| 1028 { |
| 1029 ExtensionManagementPolicyUpdater pref(&policy_provider_); |
| 1030 pref.AddRuntimeBlockedHost("*", "*://" + example_com); |
| 1031 } |
| 1032 |
| 1033 // Wait until all remote Javascript files have been pulled down. |
| 1034 ui_test_utils::NavigateToURLWithDisposition( |
| 1035 browser(), extension_test_url, WindowOpenDisposition::CURRENT_TAB, |
| 1036 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 1037 |
| 1038 // The server saw a request for the remote Javascript file. |
| 1039 EXPECT_TRUE(BrowsedTo(example2_com)); |
| 1040 |
| 1041 // The request was hidden from the extension. |
| 1042 EXPECT_EQ(1, GetCountFromBackgroundPage(extension, profile(), |
| 1043 request_counter_name)); |
| 1044 } |
| 1045 |
| 1046 // Tests that the webRequest events aren't dispatched when the URL of the |
| 1047 // request is protected by policy. |
| 1048 IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, |
| 1049 UrlProtectedByPolicy) { |
| 1050 // Host protected by policy. |
| 1051 const std::string protected_domain = "example.com"; |
| 1052 |
| 1053 { |
| 1054 ExtensionManagementPolicyUpdater pref(&policy_provider_); |
| 1055 pref.AddRuntimeBlockedHost("*", "*://" + protected_domain); |
| 1056 } |
| 1057 |
| 1058 ASSERT_TRUE(StartEmbeddedTestServer()); |
| 1059 |
| 1060 LoadExtension(test_data_dir_.AppendASCII("webrequest/policy_blocked")); |
| 1061 |
| 1062 // Listen in case extension sees the requst. |
| 1063 ExtensionTestMessageListener before_request_listener("protected_url", false); |
| 1064 |
| 1065 // Path to resolve during test navigations. |
| 1066 const std::string test_path = "/defaultresponse?protected_url"; |
| 1067 |
| 1068 // Navigate to the protected domain and wait until page fully loads. |
| 1069 ui_test_utils::NavigateToURLWithDisposition( |
| 1070 browser(), embedded_test_server()->GetURL(protected_domain, test_path), |
| 1071 WindowOpenDisposition::CURRENT_TAB, |
| 1072 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 1073 |
| 1074 // The server saw a request for the protected site. |
| 1075 EXPECT_TRUE(BrowsedTo(protected_domain)); |
| 1076 |
| 1077 // The request was hidden from the extension. |
| 1078 EXPECT_FALSE(before_request_listener.was_satisfied()); |
| 1079 |
| 1080 // Host not protected by policy. |
| 1081 const std::string unprotected_domain = "notblockedexample.com"; |
| 1082 |
| 1083 // Now we'll test browsing to a non-protected website where we expect the |
| 1084 // extension to see the request. |
| 1085 ui_test_utils::NavigateToURLWithDisposition( |
| 1086 browser(), embedded_test_server()->GetURL(unprotected_domain, test_path), |
| 1087 WindowOpenDisposition::CURRENT_TAB, |
| 1088 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 1089 |
| 1090 // The server saw a request for the non-protected site. |
| 1091 EXPECT_TRUE(BrowsedTo(unprotected_domain)); |
| 1092 |
| 1093 // The request was visible from the extension. |
| 1094 EXPECT_TRUE(before_request_listener.was_satisfied()); |
| 1095 } |
| 1096 |
| 1097 // Test that no webRequest events are seen for a protected host during normal |
| 1098 // navigation. This replicates most of the tests from |
| 1099 // WebRequestWithWithheldPermissions with a protected host. Granting a tab |
| 1100 // specific permission shouldn't bypass our policy. |
| 1101 IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, |
| 1102 WebRequestProtectedByPolicy) { |
| 1103 FeatureSwitch::ScopedOverride enable_scripts_require_action( |
| 1104 FeatureSwitch::scripts_require_action(), true); |
| 1105 |
| 1106 // Host protected by policy. |
| 1107 const std::string protected_domain = "example.com"; |
| 1108 |
| 1109 { |
| 1110 ExtensionManagementPolicyUpdater pref(&policy_provider_); |
| 1111 pref.AddRuntimeBlockedHost("*", "*://" + protected_domain); |
| 1112 } |
| 1113 |
| 1114 ASSERT_TRUE(StartEmbeddedTestServer()); |
| 1115 |
| 1116 ExtensionTestMessageListener listener("ready", false); |
| 1117 const Extension* extension = |
| 1118 LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab")); |
| 1119 ASSERT_TRUE(extension) << message_; |
| 1120 EXPECT_TRUE(listener.WaitUntilSatisfied()); |
| 1121 |
| 1122 // Navigate the browser to a page in a new tab. |
| 1123 GURL url = embedded_test_server()->GetURL(protected_domain, "/empty.html"); |
| 1124 chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); |
| 1125 params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; |
| 1126 ui_test_utils::NavigateToURL(¶ms); |
| 1127 |
| 1128 content::WebContents* web_contents = |
| 1129 browser()->tab_strip_model()->GetActiveWebContents(); |
| 1130 ASSERT_TRUE(web_contents); |
| 1131 ExtensionActionRunner* runner = |
| 1132 ExtensionActionRunner::GetForWebContents(web_contents); |
| 1133 ASSERT_TRUE(runner); |
| 1134 |
| 1135 int port = embedded_test_server()->port(); |
| 1136 const std::string kXhrPath = "simple.html"; |
| 1137 |
| 1138 // The extension shouldn't have currently received any webRequest events, |
| 1139 // since it doesn't have permission (and shouldn't receive any from an XHR). |
| 1140 EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); |
| 1141 PerformXhrInFrame(web_contents->GetMainFrame(), protected_domain, port, |
| 1142 kXhrPath); |
| 1143 EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); |
| 1144 |
| 1145 // Grant activeTab permission, and perform another XHR. The extension should |
| 1146 // still be blocked due to ExtensionSettings policy on example.com. |
| 1147 // Only records ACCESS_WITHHELD, not ACCESS_DENIED, this is why it matches |
| 1148 // BLOCKED_ACTION_NONE. |
| 1149 EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension)); |
| 1150 runner->set_default_bubble_close_action_for_testing( |
| 1151 base::WrapUnique(new ToolbarActionsBarBubbleDelegate::CloseAction( |
| 1152 ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE))); |
| 1153 runner->RunAction(extension, true); |
| 1154 base::RunLoop().RunUntilIdle(); |
| 1155 EXPECT_TRUE(content::WaitForLoadStop(web_contents)); |
| 1156 EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension)); |
| 1157 int xhr_count = GetWebRequestCountFromBackgroundPage(extension, profile()); |
| 1158 // ... which means that we should have a non-zero xhr count if the policy |
| 1159 // didn't block the events. |
| 1160 EXPECT_EQ(0, xhr_count); |
| 1161 // And the extension should also block future events. |
| 1162 PerformXhrInFrame(web_contents->GetMainFrame(), protected_domain, port, |
| 1163 kXhrPath); |
| 1164 EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); |
| 1165 } |
| 1166 |
957 } // namespace extensions | 1167 } // namespace extensions |
OLD | NEW |