OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chrome/browser/permissions/permission_request_manager.h" | 5 #include "chrome/browser/permissions/permission_request_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" | |
11 #include "chrome/browser/custom_handlers/register_protocol_handler_permission_re quest.h" | |
12 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" | |
13 #include "chrome/browser/media/webrtc/media_stream_devices_controller.h" | |
10 #include "chrome/browser/permissions/permission_context_base.h" | 14 #include "chrome/browser/permissions/permission_context_base.h" |
15 #include "chrome/browser/permissions/permission_request_impl.h" | |
11 #include "chrome/browser/permissions/permission_util.h" | 16 #include "chrome/browser/permissions/permission_util.h" |
17 #include "chrome/browser/profiles/profile.h" | |
12 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
13 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
20 #include "chrome/browser/ui/test/test_browser_dialog.h" | |
14 #include "chrome/browser/ui/website_settings/mock_permission_prompt_factory.h" | 21 #include "chrome/browser/ui/website_settings/mock_permission_prompt_factory.h" |
15 #include "chrome/test/base/in_process_browser_test.h" | 22 #include "chrome/test/base/in_process_browser_test.h" |
16 #include "chrome/test/base/ui_test_utils.h" | 23 #include "chrome/test/base/ui_test_utils.h" |
17 #include "components/content_settings/core/common/content_settings_types.h" | 24 #include "components/content_settings/core/common/content_settings_types.h" |
18 #include "components/variations/variations_associated_data.h" | 25 #include "components/variations/variations_associated_data.h" |
19 #include "content/public/test/browser_test_utils.h" | 26 #include "content/public/test/browser_test_utils.h" |
20 #include "content/public/test/test_utils.h" | 27 #include "content/public/test/test_utils.h" |
21 #include "net/test/embedded_test_server/embedded_test_server.h" | 28 #include "net/test/embedded_test_server/embedded_test_server.h" |
22 | 29 |
30 namespace test { | |
31 class MediaStreamDevicesControllerTestApi { | |
32 public: | |
33 static MediaStreamDevicesController* Create( | |
34 content::WebContents* web_contents, | |
35 const content::MediaStreamRequest& request, | |
36 const content::MediaResponseCallback& callback) { | |
37 return new MediaStreamDevicesController(web_contents, request, callback); | |
38 } | |
39 }; | |
40 } // namespace test | |
41 | |
23 namespace { | 42 namespace { |
24 | 43 |
25 const char* kPermissionsKillSwitchFieldStudy = | 44 const char* kPermissionsKillSwitchFieldStudy = |
26 PermissionContextBase::kPermissionsKillSwitchFieldStudy; | 45 PermissionContextBase::kPermissionsKillSwitchFieldStudy; |
27 const char* kPermissionsKillSwitchBlockedValue = | 46 const char* kPermissionsKillSwitchBlockedValue = |
28 PermissionContextBase::kPermissionsKillSwitchBlockedValue; | 47 PermissionContextBase::kPermissionsKillSwitchBlockedValue; |
29 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; | 48 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; |
30 | 49 |
31 class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { | 50 class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { |
32 public: | 51 public: |
(...skipping 28 matching lines...) Expand all Loading... | |
61 kPermissionsKillSwitchBlockedValue; | 80 kPermissionsKillSwitchBlockedValue; |
62 variations::AssociateVariationParams( | 81 variations::AssociateVariationParams( |
63 kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, | 82 kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, |
64 params); | 83 params); |
65 base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, | 84 base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, |
66 kPermissionsKillSwitchTestGroup); | 85 kPermissionsKillSwitchTestGroup); |
67 } | 86 } |
68 | 87 |
69 private: | 88 private: |
70 std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; | 89 std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; |
90 | |
91 DISALLOW_COPY_AND_ASSIGN(PermissionRequestManagerBrowserTest); | |
71 }; | 92 }; |
72 | 93 |
94 // Harness for testing permissions dialogs invoked by PermissionRequestManager. | |
95 // Uses a "real" PermissionPromptFactory rather than a mock. | |
96 class PermissionDialogTest | |
97 : public SupportsTestDialog<PermissionRequestManagerBrowserTest> { | |
98 public: | |
99 PermissionDialogTest() {} | |
100 | |
101 // InProcessBrowserTest: | |
102 void SetUpOnMainThread() override { | |
103 InProcessBrowserTest::SetUpOnMainThread(); // Skip super. | |
raymes
2017/03/12 23:33:53
nit: could you explain why we skip the super setup
tapted
2017/03/14 00:43:52
Done. added comment
// Skip super: It will in
| |
104 } | |
105 | |
106 private: | |
107 GURL GetUrl() { return GURL("https://example.com"); } | |
108 | |
109 PermissionRequest* MakeRegisterProtocolHandlerRequest(); | |
110 PermissionRequest* MakeMediaRequest(ContentSettingsType permission); | |
111 PermissionRequest* MakePermissionRequest(ContentSettingsType permission); | |
112 | |
113 // TestBrowserDialog: | |
114 void ShowDialog(const std::string& name) override; | |
115 | |
116 // Holds requests that do not delete themselves. | |
117 std::vector<std::unique_ptr<PermissionRequest>> owned_requests_; | |
118 | |
119 DISALLOW_COPY_AND_ASSIGN(PermissionDialogTest); | |
120 }; | |
121 | |
122 PermissionRequest* PermissionDialogTest::MakeRegisterProtocolHandlerRequest() { | |
123 std::string protocol = "mailto"; | |
124 bool user_gesture = true; | |
125 ProtocolHandler handler = | |
126 ProtocolHandler::CreateProtocolHandler(protocol, GetUrl()); | |
127 ProtocolHandlerRegistry* registry = | |
128 ProtocolHandlerRegistryFactory::GetForBrowserContext( | |
129 browser()->profile()); | |
130 // Deleted in RegisterProtocolHandlerPermissionRequest::RequestFinished(). | |
131 return new RegisterProtocolHandlerPermissionRequest(registry, handler, | |
132 GetUrl(), user_gesture); | |
133 } | |
134 | |
135 PermissionRequest* PermissionDialogTest::MakeMediaRequest( | |
136 ContentSettingsType permission) { | |
137 content::WebContents* web_contents = | |
138 browser()->tab_strip_model()->GetActiveWebContents(); | |
139 content::MediaStreamRequestType request_type = content::MEDIA_DEVICE_ACCESS; | |
140 content::MediaStreamType audio_type = content::MEDIA_NO_SERVICE; | |
141 content::MediaStreamType video_type = content::MEDIA_NO_SERVICE; | |
142 std::string audio_id = "audio_id"; | |
143 std::string video_id = "video_id"; | |
144 | |
145 if (permission == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) | |
146 audio_type = content::MEDIA_DEVICE_AUDIO_CAPTURE; | |
147 else | |
148 video_type = content::MEDIA_DEVICE_VIDEO_CAPTURE; | |
149 content::MediaStreamRequest request(0, 0, 0, GetUrl(), false, request_type, | |
150 audio_id, video_id, audio_type, | |
151 video_type, false); | |
152 | |
153 // Add fake devices, otherwise the request will auto-block. | |
154 MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices( | |
155 content::MediaStreamDevices( | |
156 1, content::MediaStreamDevice(content::MEDIA_DEVICE_AUDIO_CAPTURE, | |
157 audio_id, "Fake Audio"))); | |
158 MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices( | |
159 content::MediaStreamDevices( | |
160 1, content::MediaStreamDevice(content::MEDIA_DEVICE_VIDEO_CAPTURE, | |
161 video_id, "Fake Video"))); | |
162 | |
163 auto response = [](const content::MediaStreamDevices& devices, | |
164 content::MediaStreamRequestResult result, | |
165 std::unique_ptr<content::MediaStreamUI> ui) {}; | |
166 // Deleted in MediaStreamDevicesController::RequestFinished(). | |
167 return test::MediaStreamDevicesControllerTestApi::Create( | |
168 web_contents, request, base::Bind(response)); | |
169 } | |
170 | |
171 PermissionRequest* PermissionDialogTest::MakePermissionRequest( | |
172 ContentSettingsType permission) { | |
173 bool user_gesture = true; | |
174 auto decided = [](bool, ContentSetting) {}; | |
175 auto cleanup = [] {}; // Leave cleanup to test harness destructor. | |
176 owned_requests_.push_back(base::MakeUnique<PermissionRequestImpl>( | |
177 GetUrl(), permission, browser()->profile(), user_gesture, | |
178 base::Bind(decided), base::Bind(cleanup))); | |
179 return owned_requests_.back().get(); | |
180 } | |
181 | |
182 void PermissionDialogTest::ShowDialog(const std::string& name) { | |
183 constexpr const char* kMultipleName = "multiple"; | |
184 // Permissions to request for a "multiple" request. Only types handled in | |
185 // PermissionRequestImpl::GetMessageTextFragment() are valid. | |
186 constexpr ContentSettingsType kMultipleRequests[] = { | |
187 CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, | |
188 CONTENT_SETTINGS_TYPE_MIDI_SYSEX}; | |
189 constexpr struct { | |
190 const char* name; | |
191 ContentSettingsType type; | |
192 } kNameToType[] = { | |
193 {"flash", CONTENT_SETTINGS_TYPE_PLUGINS}, | |
194 {"geolocation", CONTENT_SETTINGS_TYPE_GEOLOCATION}, | |
195 {"protected_media", CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER}, | |
196 {"notifications", CONTENT_SETTINGS_TYPE_NOTIFICATIONS}, | |
197 {"mic", CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC}, | |
198 {"camera", CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA}, | |
199 {"protocol_handlers", CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS}, | |
200 {"midi", CONTENT_SETTINGS_TYPE_MIDI_SYSEX}, | |
201 {kMultipleName, CONTENT_SETTINGS_TYPE_DEFAULT}}; | |
202 const auto* it = std::begin(kNameToType); | |
203 for (; it != std::end(kNameToType); ++it) { | |
204 if (name == it->name) | |
205 break; | |
206 } | |
207 if (it == std::end(kNameToType)) { | |
208 ADD_FAILURE() << "Unknown: " << name; | |
209 return; | |
210 } | |
211 PermissionRequestManager* manager = GetPermissionRequestManager(); | |
212 switch (it->type) { | |
213 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS: | |
214 manager->AddRequest(MakeRegisterProtocolHandlerRequest()); | |
215 break; | |
216 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: | |
217 // TODO(tapted): Prompt for downloading multiple files. | |
218 break; | |
219 case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: | |
220 // TODO(tapted): Prompt for quota request. | |
221 break; | |
222 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: | |
223 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: | |
224 manager->AddRequest(MakeMediaRequest(it->type)); | |
225 break; | |
226 // Regular permissions requests. | |
227 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: | |
228 case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING: // Same as notifications. | |
229 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: | |
230 case CONTENT_SETTINGS_TYPE_GEOLOCATION: | |
231 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: // ChromeOS only. | |
232 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: | |
233 case CONTENT_SETTINGS_TYPE_PLUGINS: // Flash. | |
234 manager->AddRequest(MakePermissionRequest(it->type)); | |
235 break; | |
236 case CONTENT_SETTINGS_TYPE_MIDI: // Disabled (no icon). | |
raymes
2017/03/12 23:33:53
This one actually doesn't prompt either.
tapted
2017/03/14 00:43:53
Done.
| |
237 case CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC: // Disabled (doesn't prompt). | |
238 ADD_FAILURE() << "PermissionType, but doesn't prompt."; | |
239 return; | |
240 case CONTENT_SETTINGS_TYPE_COOKIES: | |
241 case CONTENT_SETTINGS_TYPE_IMAGES: | |
242 case CONTENT_SETTINGS_TYPE_JAVASCRIPT: | |
243 case CONTENT_SETTINGS_TYPE_POPUPS: | |
244 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE: | |
245 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT: | |
246 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS: | |
247 case CONTENT_SETTINGS_TYPE_APP_BANNER: | |
248 case CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT: | |
249 case CONTENT_SETTINGS_TYPE_USB_CHOOSER_DATA: | |
250 case CONTENT_SETTINGS_TYPE_BLUETOOTH_GUARD: | |
251 case CONTENT_SETTINGS_TYPE_AUTOPLAY: | |
252 case CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT: | |
253 case CONTENT_SETTINGS_TYPE_IMPORTANT_SITE_INFO: | |
254 case CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA: | |
255 case CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER: | |
256 case CONTENT_SETTINGS_NUM_TYPES_DO_NOT_USE: | |
257 ADD_FAILURE() << "Not a permission prompt."; | |
258 return; | |
259 case CONTENT_SETTINGS_TYPE_DEFAULT: | |
260 EXPECT_EQ(kMultipleName, name); | |
261 for (auto request : kMultipleRequests) | |
262 manager->AddRequest(MakePermissionRequest(request)); | |
263 break; | |
264 // No default case, to pick up new enum values. | |
raymes
2017/03/12 23:33:53
I'd actually suggest adding default: here because
tapted
2017/03/14 00:43:52
Done.
| |
265 } | |
266 manager->DisplayPendingRequests(); | |
267 } | |
268 | |
73 // Requests before the load event should be bundled into one bubble. | 269 // Requests before the load event should be bundled into one bubble. |
74 // http://crbug.com/512849 flaky | 270 // http://crbug.com/512849 flaky |
75 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, | 271 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, |
76 DISABLED_RequestsBeforeLoad) { | 272 DISABLED_RequestsBeforeLoad) { |
77 ASSERT_TRUE(embedded_test_server()->Start()); | 273 ASSERT_TRUE(embedded_test_server()->Start()); |
78 | 274 |
79 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( | 275 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( |
80 browser(), | 276 browser(), |
81 embedded_test_server()->GetURL("/permissions/requests-before-load.html"), | 277 embedded_test_server()->GetURL("/permissions/requests-before-load.html"), |
82 1); | 278 1); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 | 437 |
242 // Disable the trial. | 438 // Disable the trial. |
243 variations::testing::ClearAllVariationParams(); | 439 variations::testing::ClearAllVariationParams(); |
244 | 440 |
245 EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); | 441 EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); |
246 bubble_factory()->WaitForPermissionBubble(); | 442 bubble_factory()->WaitForPermissionBubble(); |
247 EXPECT_EQ(1, bubble_factory()->show_count()); | 443 EXPECT_EQ(1, bubble_factory()->show_count()); |
248 EXPECT_EQ(1, bubble_factory()->total_request_count()); | 444 EXPECT_EQ(1, bubble_factory()->total_request_count()); |
249 } | 445 } |
250 | 446 |
447 // Host wants to run flash. | |
448 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_flash) { | |
449 RunDialog(); | |
450 } | |
451 | |
452 // Host wants to know your location. | |
453 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_geolocation) { | |
454 RunDialog(); | |
455 } | |
456 | |
457 // Host wants to show notifications. | |
458 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_notifications) { | |
459 RunDialog(); | |
460 } | |
461 | |
462 // Host wants to use your microphone. | |
463 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_mic) { | |
464 RunDialog(); | |
465 } | |
466 | |
467 // Host wants to use your camera. | |
468 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_camera) { | |
469 RunDialog(); | |
470 } | |
471 | |
472 // Host wants to open email links. | |
473 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_protocol_handlers) { | |
474 RunDialog(); | |
475 } | |
476 | |
477 // Host wants to use your MIDI devices. | |
478 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_midi) { | |
479 RunDialog(); | |
480 } | |
481 | |
482 // Shows a permissions bubble with multiple requests. | |
483 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_multiple) { | |
484 RunDialog(); | |
485 } | |
486 | |
487 // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER is ChromeOS only. | |
488 #if defined(OS_CHROMEOS) | |
489 #define MAYBE_InvokeDialog_protected_media InvokeDialog_protected_media | |
490 #else | |
491 #define MAYBE_InvokeDialog_protected_media DISABLED_InvokeDialog_protected_media | |
492 #endif | |
493 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, | |
494 MAYBE_InvokeDialog_protected_media) { | |
495 RunDialog(); | |
496 } | |
497 | |
251 } // anonymous namespace | 498 } // anonymous namespace |
OLD | NEW |