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 MediaStreamDevicesController::PermissionPromptDelegate { |
| 33 public: |
| 34 static void AddRequestToManager( |
| 35 PermissionRequestManager* manager, |
| 36 content::WebContents* web_contents, |
| 37 const content::MediaStreamRequest& request, |
| 38 const content::MediaResponseCallback& callback) { |
| 39 MediaStreamDevicesControllerTestApi delegate(manager); |
| 40 MediaStreamDevicesController::RequestPermissionsWithDelegate( |
| 41 web_contents, request, callback, &delegate); |
| 42 } |
| 43 |
| 44 private: |
| 45 // MediaStreamDevicesController::PermissionPromptDelegate: |
| 46 void ShowPrompt( |
| 47 bool user_gesture, |
| 48 content::WebContents* web_contents, |
| 49 std::unique_ptr<MediaStreamDevicesController> controller) override { |
| 50 manager_->AddRequest(controller.release()); |
| 51 } |
| 52 |
| 53 explicit MediaStreamDevicesControllerTestApi( |
| 54 PermissionRequestManager* manager) |
| 55 : manager_(manager) {} |
| 56 |
| 57 PermissionRequestManager* manager_; |
| 58 |
| 59 DISALLOW_COPY_AND_ASSIGN(MediaStreamDevicesControllerTestApi); |
| 60 }; |
| 61 } // namespace test |
| 62 |
23 namespace { | 63 namespace { |
24 | 64 |
25 const char* kPermissionsKillSwitchFieldStudy = | 65 const char* kPermissionsKillSwitchFieldStudy = |
26 PermissionContextBase::kPermissionsKillSwitchFieldStudy; | 66 PermissionContextBase::kPermissionsKillSwitchFieldStudy; |
27 const char* kPermissionsKillSwitchBlockedValue = | 67 const char* kPermissionsKillSwitchBlockedValue = |
28 PermissionContextBase::kPermissionsKillSwitchBlockedValue; | 68 PermissionContextBase::kPermissionsKillSwitchBlockedValue; |
29 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; | 69 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; |
30 | 70 |
31 class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { | 71 class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { |
32 public: | 72 public: |
(...skipping 28 matching lines...) Expand all Loading... |
61 kPermissionsKillSwitchBlockedValue; | 101 kPermissionsKillSwitchBlockedValue; |
62 variations::AssociateVariationParams( | 102 variations::AssociateVariationParams( |
63 kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, | 103 kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, |
64 params); | 104 params); |
65 base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, | 105 base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, |
66 kPermissionsKillSwitchTestGroup); | 106 kPermissionsKillSwitchTestGroup); |
67 } | 107 } |
68 | 108 |
69 private: | 109 private: |
70 std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; | 110 std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; |
| 111 |
| 112 DISALLOW_COPY_AND_ASSIGN(PermissionRequestManagerBrowserTest); |
71 }; | 113 }; |
72 | 114 |
| 115 // Harness for testing permissions dialogs invoked by PermissionRequestManager. |
| 116 // Uses a "real" PermissionPromptFactory rather than a mock. |
| 117 class PermissionDialogTest |
| 118 : public SupportsTestDialog<PermissionRequestManagerBrowserTest> { |
| 119 public: |
| 120 PermissionDialogTest() {} |
| 121 |
| 122 // InProcessBrowserTest: |
| 123 void SetUpOnMainThread() override { |
| 124 // Skip super: It will install a mock permission UI factory, but for this |
| 125 // test we want to show "real" UI. |
| 126 InProcessBrowserTest::SetUpOnMainThread(); |
| 127 } |
| 128 |
| 129 private: |
| 130 GURL GetUrl() { return GURL("https://example.com"); } |
| 131 |
| 132 PermissionRequest* MakeRegisterProtocolHandlerRequest(); |
| 133 void AddMediaRequest(PermissionRequestManager* manager, |
| 134 ContentSettingsType permission); |
| 135 PermissionRequest* MakePermissionRequest(ContentSettingsType permission); |
| 136 |
| 137 // TestBrowserDialog: |
| 138 void ShowDialog(const std::string& name) override; |
| 139 |
| 140 // Holds requests that do not delete themselves. |
| 141 std::vector<std::unique_ptr<PermissionRequest>> owned_requests_; |
| 142 |
| 143 DISALLOW_COPY_AND_ASSIGN(PermissionDialogTest); |
| 144 }; |
| 145 |
| 146 PermissionRequest* PermissionDialogTest::MakeRegisterProtocolHandlerRequest() { |
| 147 std::string protocol = "mailto"; |
| 148 bool user_gesture = true; |
| 149 ProtocolHandler handler = |
| 150 ProtocolHandler::CreateProtocolHandler(protocol, GetUrl()); |
| 151 ProtocolHandlerRegistry* registry = |
| 152 ProtocolHandlerRegistryFactory::GetForBrowserContext( |
| 153 browser()->profile()); |
| 154 // Deleted in RegisterProtocolHandlerPermissionRequest::RequestFinished(). |
| 155 return new RegisterProtocolHandlerPermissionRequest(registry, handler, |
| 156 GetUrl(), user_gesture); |
| 157 } |
| 158 |
| 159 void PermissionDialogTest::AddMediaRequest(PermissionRequestManager* manager, |
| 160 ContentSettingsType permission) { |
| 161 content::WebContents* web_contents = |
| 162 browser()->tab_strip_model()->GetActiveWebContents(); |
| 163 content::MediaStreamRequestType request_type = content::MEDIA_DEVICE_ACCESS; |
| 164 content::MediaStreamType audio_type = content::MEDIA_NO_SERVICE; |
| 165 content::MediaStreamType video_type = content::MEDIA_NO_SERVICE; |
| 166 std::string audio_id = "audio_id"; |
| 167 std::string video_id = "video_id"; |
| 168 |
| 169 if (permission == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) |
| 170 audio_type = content::MEDIA_DEVICE_AUDIO_CAPTURE; |
| 171 else |
| 172 video_type = content::MEDIA_DEVICE_VIDEO_CAPTURE; |
| 173 content::MediaStreamRequest request(0, 0, 0, GetUrl(), false, request_type, |
| 174 audio_id, video_id, audio_type, |
| 175 video_type, false); |
| 176 |
| 177 // Add fake devices, otherwise the request will auto-block. |
| 178 MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices( |
| 179 content::MediaStreamDevices( |
| 180 1, content::MediaStreamDevice(content::MEDIA_DEVICE_AUDIO_CAPTURE, |
| 181 audio_id, "Fake Audio"))); |
| 182 MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices( |
| 183 content::MediaStreamDevices( |
| 184 1, content::MediaStreamDevice(content::MEDIA_DEVICE_VIDEO_CAPTURE, |
| 185 video_id, "Fake Video"))); |
| 186 |
| 187 auto response = [](const content::MediaStreamDevices& devices, |
| 188 content::MediaStreamRequestResult result, |
| 189 std::unique_ptr<content::MediaStreamUI> ui) {}; |
| 190 test::MediaStreamDevicesControllerTestApi::AddRequestToManager( |
| 191 manager, web_contents, request, base::Bind(response)); |
| 192 } |
| 193 |
| 194 PermissionRequest* PermissionDialogTest::MakePermissionRequest( |
| 195 ContentSettingsType permission) { |
| 196 bool user_gesture = true; |
| 197 auto decided = [](bool, ContentSetting) {}; |
| 198 auto cleanup = [] {}; // Leave cleanup to test harness destructor. |
| 199 owned_requests_.push_back(base::MakeUnique<PermissionRequestImpl>( |
| 200 GetUrl(), permission, browser()->profile(), user_gesture, |
| 201 base::Bind(decided), base::Bind(cleanup))); |
| 202 return owned_requests_.back().get(); |
| 203 } |
| 204 |
| 205 void PermissionDialogTest::ShowDialog(const std::string& name) { |
| 206 constexpr const char* kMultipleName = "multiple"; |
| 207 // Permissions to request for a "multiple" request. Only types handled in |
| 208 // PermissionRequestImpl::GetMessageTextFragment() are valid. |
| 209 constexpr ContentSettingsType kMultipleRequests[] = { |
| 210 CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, |
| 211 CONTENT_SETTINGS_TYPE_MIDI_SYSEX}; |
| 212 constexpr struct { |
| 213 const char* name; |
| 214 ContentSettingsType type; |
| 215 } kNameToType[] = { |
| 216 {"flash", CONTENT_SETTINGS_TYPE_PLUGINS}, |
| 217 {"geolocation", CONTENT_SETTINGS_TYPE_GEOLOCATION}, |
| 218 {"protected_media", CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER}, |
| 219 {"notifications", CONTENT_SETTINGS_TYPE_NOTIFICATIONS}, |
| 220 {"mic", CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC}, |
| 221 {"camera", CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA}, |
| 222 {"protocol_handlers", CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS}, |
| 223 {"midi", CONTENT_SETTINGS_TYPE_MIDI_SYSEX}, |
| 224 {kMultipleName, CONTENT_SETTINGS_TYPE_DEFAULT}}; |
| 225 const auto* it = std::begin(kNameToType); |
| 226 for (; it != std::end(kNameToType); ++it) { |
| 227 if (name == it->name) |
| 228 break; |
| 229 } |
| 230 if (it == std::end(kNameToType)) { |
| 231 ADD_FAILURE() << "Unknown: " << name; |
| 232 return; |
| 233 } |
| 234 PermissionRequestManager* manager = GetPermissionRequestManager(); |
| 235 switch (it->type) { |
| 236 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS: |
| 237 manager->AddRequest(MakeRegisterProtocolHandlerRequest()); |
| 238 break; |
| 239 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: |
| 240 // TODO(tapted): Prompt for downloading multiple files. |
| 241 break; |
| 242 case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: |
| 243 // TODO(tapted): Prompt for quota request. |
| 244 break; |
| 245 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: |
| 246 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: |
| 247 AddMediaRequest(manager, it->type); |
| 248 break; |
| 249 // Regular permissions requests. |
| 250 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: |
| 251 case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING: // Same as notifications. |
| 252 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
| 253 case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
| 254 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: // ChromeOS only. |
| 255 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: |
| 256 case CONTENT_SETTINGS_TYPE_PLUGINS: // Flash. |
| 257 manager->AddRequest(MakePermissionRequest(it->type)); |
| 258 break; |
| 259 case CONTENT_SETTINGS_TYPE_DEFAULT: |
| 260 EXPECT_EQ(kMultipleName, name); |
| 261 for (auto request : kMultipleRequests) |
| 262 manager->AddRequest(MakePermissionRequest(request)); |
| 263 break; |
| 264 default: |
| 265 ADD_FAILURE() << "Not a permission type, or one that doesn't prompt."; |
| 266 return; |
| 267 } |
| 268 manager->DisplayPendingRequests(); |
| 269 } |
| 270 |
73 // Requests before the load event should be bundled into one bubble. | 271 // Requests before the load event should be bundled into one bubble. |
74 // http://crbug.com/512849 flaky | 272 // http://crbug.com/512849 flaky |
75 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, | 273 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, |
76 DISABLED_RequestsBeforeLoad) { | 274 DISABLED_RequestsBeforeLoad) { |
77 ASSERT_TRUE(embedded_test_server()->Start()); | 275 ASSERT_TRUE(embedded_test_server()->Start()); |
78 | 276 |
79 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( | 277 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( |
80 browser(), | 278 browser(), |
81 embedded_test_server()->GetURL("/permissions/requests-before-load.html"), | 279 embedded_test_server()->GetURL("/permissions/requests-before-load.html"), |
82 1); | 280 1); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 | 439 |
242 // Disable the trial. | 440 // Disable the trial. |
243 variations::testing::ClearAllVariationParams(); | 441 variations::testing::ClearAllVariationParams(); |
244 | 442 |
245 EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); | 443 EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); |
246 bubble_factory()->WaitForPermissionBubble(); | 444 bubble_factory()->WaitForPermissionBubble(); |
247 EXPECT_EQ(1, bubble_factory()->show_count()); | 445 EXPECT_EQ(1, bubble_factory()->show_count()); |
248 EXPECT_EQ(1, bubble_factory()->total_request_count()); | 446 EXPECT_EQ(1, bubble_factory()->total_request_count()); |
249 } | 447 } |
250 | 448 |
| 449 // Host wants to run flash. |
| 450 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_flash) { |
| 451 RunDialog(); |
| 452 } |
| 453 |
| 454 // Host wants to know your location. |
| 455 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_geolocation) { |
| 456 RunDialog(); |
| 457 } |
| 458 |
| 459 // Host wants to show notifications. |
| 460 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_notifications) { |
| 461 RunDialog(); |
| 462 } |
| 463 |
| 464 // Host wants to use your microphone. |
| 465 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_mic) { |
| 466 RunDialog(); |
| 467 } |
| 468 |
| 469 // Host wants to use your camera. |
| 470 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_camera) { |
| 471 RunDialog(); |
| 472 } |
| 473 |
| 474 // Host wants to open email links. |
| 475 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_protocol_handlers) { |
| 476 RunDialog(); |
| 477 } |
| 478 |
| 479 // Host wants to use your MIDI devices. |
| 480 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_midi) { |
| 481 RunDialog(); |
| 482 } |
| 483 |
| 484 // Shows a permissions bubble with multiple requests. |
| 485 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_multiple) { |
| 486 RunDialog(); |
| 487 } |
| 488 |
| 489 // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER is ChromeOS only. |
| 490 #if defined(OS_CHROMEOS) |
| 491 #define MAYBE_InvokeDialog_protected_media InvokeDialog_protected_media |
| 492 #else |
| 493 #define MAYBE_InvokeDialog_protected_media DISABLED_InvokeDialog_protected_media |
| 494 #endif |
| 495 IN_PROC_BROWSER_TEST_F(PermissionDialogTest, |
| 496 MAYBE_InvokeDialog_protected_media) { |
| 497 RunDialog(); |
| 498 } |
| 499 |
251 } // anonymous namespace | 500 } // anonymous namespace |
OLD | NEW |