| 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" |
| 12 #include "chrome/browser/ui/browser.h" | 17 #include "chrome/browser/ui/browser.h" |
| 13 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 18 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 19 #include "chrome/browser/ui/test/test_browser_dialog.h" |
| 14 #include "chrome/browser/ui/website_settings/mock_permission_prompt_factory.h" | 20 #include "chrome/browser/ui/website_settings/mock_permission_prompt_factory.h" |
| 15 #include "chrome/test/base/in_process_browser_test.h" | 21 #include "chrome/test/base/in_process_browser_test.h" |
| 16 #include "chrome/test/base/ui_test_utils.h" | 22 #include "chrome/test/base/ui_test_utils.h" |
| 17 #include "components/variations/variations_associated_data.h" | 23 #include "components/variations/variations_associated_data.h" |
| 18 #include "content/public/browser/permission_type.h" | 24 #include "content/public/browser/permission_type.h" |
| 19 #include "content/public/test/browser_test_utils.h" | 25 #include "content/public/test/browser_test_utils.h" |
| 20 #include "content/public/test/test_utils.h" | 26 #include "content/public/test/test_utils.h" |
| 21 #include "net/test/embedded_test_server/embedded_test_server.h" | 27 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 22 | 28 |
| 29 using content::PermissionType; |
| 30 |
| 23 namespace { | 31 namespace { |
| 24 | 32 |
| 25 const char* kPermissionsKillSwitchFieldStudy = | 33 const char* kPermissionsKillSwitchFieldStudy = |
| 26 PermissionContextBase::kPermissionsKillSwitchFieldStudy; | 34 PermissionContextBase::kPermissionsKillSwitchFieldStudy; |
| 27 const char* kPermissionsKillSwitchBlockedValue = | 35 const char* kPermissionsKillSwitchBlockedValue = |
| 28 PermissionContextBase::kPermissionsKillSwitchBlockedValue; | 36 PermissionContextBase::kPermissionsKillSwitchBlockedValue; |
| 29 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; | 37 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; |
| 30 | 38 |
| 31 class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { | 39 class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { |
| 32 public: | 40 public: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 48 | 56 |
| 49 PermissionRequestManager* GetPermissionRequestManager() { | 57 PermissionRequestManager* GetPermissionRequestManager() { |
| 50 return PermissionRequestManager::FromWebContents( | 58 return PermissionRequestManager::FromWebContents( |
| 51 browser()->tab_strip_model()->GetActiveWebContents()); | 59 browser()->tab_strip_model()->GetActiveWebContents()); |
| 52 } | 60 } |
| 53 | 61 |
| 54 MockPermissionPromptFactory* bubble_factory() { | 62 MockPermissionPromptFactory* bubble_factory() { |
| 55 return mock_permission_prompt_factory_.get(); | 63 return mock_permission_prompt_factory_.get(); |
| 56 } | 64 } |
| 57 | 65 |
| 58 void EnableKillSwitch(content::PermissionType permission_type) { | 66 void EnableKillSwitch(PermissionType permission_type) { |
| 59 std::map<std::string, std::string> params; | 67 std::map<std::string, std::string> params; |
| 60 params[PermissionUtil::GetPermissionString(permission_type)] = | 68 params[PermissionUtil::GetPermissionString(permission_type)] = |
| 61 kPermissionsKillSwitchBlockedValue; | 69 kPermissionsKillSwitchBlockedValue; |
| 62 variations::AssociateVariationParams( | 70 variations::AssociateVariationParams( |
| 63 kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, | 71 kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, |
| 64 params); | 72 params); |
| 65 base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, | 73 base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, |
| 66 kPermissionsKillSwitchTestGroup); | 74 kPermissionsKillSwitchTestGroup); |
| 67 } | 75 } |
| 68 | 76 |
| 69 private: | 77 private: |
| 70 std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; | 78 std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; |
| 79 |
| 80 DISALLOW_COPY_AND_ASSIGN(PermissionRequestManagerBrowserTest); |
| 71 }; | 81 }; |
| 72 | 82 |
| 83 // Harness for testing permissions dialogs invoked by PermissionRequestManager. |
| 84 // Uses a "real" PermissionPromptFactory rather than a mock. |
| 85 class PermissionDialogTest |
| 86 : public SupportsTestDialog<PermissionRequestManagerBrowserTest> { |
| 87 public: |
| 88 // Values for dialog styles that are not a content::PermissionType. |
| 89 enum CustomPermissionTypes { |
| 90 REGISTER_PROTOCOL_HANDLER = 0, |
| 91 MULTIPLE_REQUESTS = static_cast<int>(PermissionType::NUM), |
| 92 |
| 93 // TODO(tapted): Implement these: |
| 94 DOWNLOAD_MULTIPLE_FILES, |
| 95 QUOTA_REQUEST, |
| 96 }; |
| 97 |
| 98 PermissionDialogTest() {} |
| 99 |
| 100 // InProcessBrowserTest: |
| 101 void SetUpOnMainThread() override { |
| 102 InProcessBrowserTest::SetUpOnMainThread(); // Skip super. |
| 103 } |
| 104 |
| 105 static std::vector<std::string> NameProvider() { |
| 106 // Put RegisterProtocolHandler at index 0. There is no PermissionType with |
| 107 // value 0, and no PermissionType for RPH, even though there is a request |
| 108 // class for it. ShowDialog is called with index 0 when no dialog is chosen. |
| 109 std::vector<std::string> names = {"RegisterProtocolHandler"}; |
| 110 auto add = [&names](PermissionType type, const std::string& name) { |
| 111 EXPECT_EQ(names.size(), static_cast<size_t>(type)); |
| 112 names.push_back(name); |
| 113 }; |
| 114 add(PermissionType::MIDI_SYSEX, "MidiSysex"); |
| 115 |
| 116 // Note: The next 2 look kinda the same. |
| 117 add(PermissionType::PUSH_MESSAGING, "PushMessaging"); |
| 118 add(PermissionType::NOTIFICATIONS, "Notifications"); |
| 119 |
| 120 add(PermissionType::GEOLOCATION, "Geolocation"); |
| 121 |
| 122 #if defined(OS_CHROMEOS) |
| 123 // ProtectedMedia is ChromeOS only (fails with no icon otherwise). |
| 124 add(PermissionType::PROTECTED_MEDIA_IDENTIFIER, "ProtectedMedia"); |
| 125 #else |
| 126 add(PermissionType::PROTECTED_MEDIA_IDENTIFIER, "DISABLED_ProtectedMedia"); |
| 127 #endif |
| 128 |
| 129 // Note: This fails because there is no icon. |
| 130 add(PermissionType::MIDI, "DISABLED_Midi"); |
| 131 |
| 132 // Note: Doesn't prompt. See durable_storage_permission_context.cc. |
| 133 add(PermissionType::DURABLE_STORAGE, "DISABLED_DurableStorage"); |
| 134 |
| 135 add(PermissionType::AUDIO_CAPTURE, "AudioCapture"); |
| 136 add(PermissionType::VIDEO_CAPTURE, "VideoCapture"); |
| 137 |
| 138 // Note: Doesn't prompt. See background_sync_manager.cc. |
| 139 add(PermissionType::BACKGROUND_SYNC, "DISABLED_BackgroundSync"); |
| 140 |
| 141 add(PermissionType::FLASH, "Flash"); |
| 142 static_assert(static_cast<int>(PermissionType::NUM) == 12, |
| 143 "PermissionType count changed. Please update dialog tests."); |
| 144 |
| 145 EXPECT_EQ(names.size(), MULTIPLE_REQUESTS); |
| 146 names.push_back("MultipleRequests"); |
| 147 return names; |
| 148 } |
| 149 |
| 150 GURL GetUrl() { return GURL("https://example.com"); } |
| 151 |
| 152 PermissionRequest* MakeRegisterProtocolHandlerRequest() { |
| 153 std::string protocol = "mailto"; |
| 154 bool user_gesture = true; |
| 155 ProtocolHandler handler = |
| 156 ProtocolHandler::CreateProtocolHandler(protocol, GetUrl()); |
| 157 ProtocolHandlerRegistry* registry = |
| 158 ProtocolHandlerRegistryFactory::GetForBrowserContext( |
| 159 browser()->profile()); |
| 160 // Deleted in RegisterProtocolHandlerPermissionRequest::RequestFinished(). |
| 161 return new RegisterProtocolHandlerPermissionRequest(registry, handler, |
| 162 GetUrl(), user_gesture); |
| 163 } |
| 164 |
| 165 PermissionRequest* MakeMediaRequest(PermissionType permission) { |
| 166 content::WebContents* web_contents = |
| 167 browser()->tab_strip_model()->GetActiveWebContents(); |
| 168 content::MediaStreamRequestType request_type = content::MEDIA_DEVICE_ACCESS; |
| 169 content::MediaStreamType audio_type = content::MEDIA_NO_SERVICE; |
| 170 content::MediaStreamType video_type = content::MEDIA_NO_SERVICE; |
| 171 std::string audio_id = "audio_id"; |
| 172 std::string video_id = "video_id"; |
| 173 |
| 174 if (permission == PermissionType::AUDIO_CAPTURE) |
| 175 audio_type = content::MEDIA_DEVICE_AUDIO_CAPTURE; |
| 176 else |
| 177 video_type = content::MEDIA_DEVICE_VIDEO_CAPTURE; |
| 178 content::MediaStreamRequest request(0, 0, 0, GetUrl(), false, request_type, |
| 179 audio_id, video_id, audio_type, |
| 180 video_type, false); |
| 181 |
| 182 // Add fake devices, otherwise the request will auto-block. |
| 183 MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices( |
| 184 content::MediaStreamDevices( |
| 185 1, content::MediaStreamDevice(content::MEDIA_DEVICE_AUDIO_CAPTURE, |
| 186 audio_id, "Fake Audio"))); |
| 187 MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices( |
| 188 content::MediaStreamDevices( |
| 189 1, content::MediaStreamDevice(content::MEDIA_DEVICE_VIDEO_CAPTURE, |
| 190 video_id, "Fake Video"))); |
| 191 |
| 192 auto response = [](const content::MediaStreamDevices& devices, |
| 193 content::MediaStreamRequestResult result, |
| 194 std::unique_ptr<content::MediaStreamUI> ui) {}; |
| 195 // Deleted in MediaStreamDevicesController::RequestFinished(). |
| 196 return new MediaStreamDevicesController(web_contents, request, |
| 197 base::Bind(response)); |
| 198 } |
| 199 |
| 200 PermissionRequest* MakeRequest(PermissionType permission) { |
| 201 if (permission == PermissionType::AUDIO_CAPTURE || |
| 202 permission == PermissionType::VIDEO_CAPTURE) |
| 203 return MakeMediaRequest(permission); |
| 204 |
| 205 bool user_gesture = true; |
| 206 auto decided = [](bool, ContentSetting) {}; |
| 207 auto cleanup = [] {}; // Leave cleanup to test harness destructor. |
| 208 owned_requests_.push_back(base::MakeUnique<PermissionRequestImpl>( |
| 209 GetUrl(), permission, browser()->profile(), user_gesture, |
| 210 base::Bind(decided), base::Bind(cleanup))); |
| 211 return owned_requests_.back().get(); |
| 212 } |
| 213 |
| 214 // TestDialogInterface: |
| 215 void ShowDialog(int index) override { |
| 216 PermissionRequestManager* manager = GetPermissionRequestManager(); |
| 217 if (index == REGISTER_PROTOCOL_HANDLER) { |
| 218 manager->AddRequest(MakeRegisterProtocolHandlerRequest()); |
| 219 } else if (index < static_cast<int>(PermissionType::NUM)) { |
| 220 PermissionType permission = static_cast<PermissionType>(index); |
| 221 manager->AddRequest(MakeRequest(permission)); |
| 222 } else if (index == MULTIPLE_REQUESTS) { |
| 223 // Only types handled in PermissionRequestImpl::GetMessageTextFragment() |
| 224 // can be combined this way. |
| 225 manager->AddRequest(MakeRequest(PermissionType::GEOLOCATION)); |
| 226 manager->AddRequest(MakeRequest(PermissionType::NOTIFICATIONS)); |
| 227 manager->AddRequest(MakeRequest(PermissionType::MIDI_SYSEX)); |
| 228 } else { |
| 229 NOTREACHED(); |
| 230 } |
| 231 manager->DisplayPendingRequests(); |
| 232 } |
| 233 |
| 234 private: |
| 235 std::vector<std::unique_ptr<PermissionRequest>> owned_requests_; |
| 236 |
| 237 DISALLOW_COPY_AND_ASSIGN(PermissionDialogTest); |
| 238 }; |
| 239 |
| 240 TEST_BROWSER_DIALOG(PermissionDialogTest); |
| 241 |
| 73 // Requests before the load event should be bundled into one bubble. | 242 // Requests before the load event should be bundled into one bubble. |
| 74 // http://crbug.com/512849 flaky | 243 // http://crbug.com/512849 flaky |
| 75 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, | 244 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, |
| 76 DISABLED_RequestsBeforeLoad) { | 245 DISABLED_RequestsBeforeLoad) { |
| 77 ASSERT_TRUE(embedded_test_server()->Start()); | 246 ASSERT_TRUE(embedded_test_server()->Start()); |
| 78 | 247 |
| 79 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( | 248 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( |
| 80 browser(), | 249 browser(), |
| 81 embedded_test_server()->GetURL("/permissions/requests-before-load.html"), | 250 embedded_test_server()->GetURL("/permissions/requests-before-load.html"), |
| 82 1); | 251 1); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // Bubble requests should not be shown when the killswitch is on. | 354 // Bubble requests should not be shown when the killswitch is on. |
| 186 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, | 355 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, |
| 187 KillSwitchGeolocation) { | 356 KillSwitchGeolocation) { |
| 188 ASSERT_TRUE(embedded_test_server()->Start()); | 357 ASSERT_TRUE(embedded_test_server()->Start()); |
| 189 | 358 |
| 190 ui_test_utils::NavigateToURL( | 359 ui_test_utils::NavigateToURL( |
| 191 browser(), | 360 browser(), |
| 192 embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); | 361 embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); |
| 193 | 362 |
| 194 // Now enable the geolocation killswitch. | 363 // Now enable the geolocation killswitch. |
| 195 EnableKillSwitch(content::PermissionType::GEOLOCATION); | 364 EnableKillSwitch(PermissionType::GEOLOCATION); |
| 196 content::WebContents* web_contents = | 365 content::WebContents* web_contents = |
| 197 browser()->tab_strip_model()->GetActiveWebContents(); | 366 browser()->tab_strip_model()->GetActiveWebContents(); |
| 198 | 367 |
| 199 std::string result; | 368 std::string result; |
| 200 EXPECT_TRUE(content::ExecuteScriptAndExtractString( | 369 EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
| 201 web_contents, "requestGeolocation();", &result)); | 370 web_contents, "requestGeolocation();", &result)); |
| 202 EXPECT_EQ("denied", result); | 371 EXPECT_EQ("denied", result); |
| 203 EXPECT_EQ(0, bubble_factory()->show_count()); | 372 EXPECT_EQ(0, bubble_factory()->show_count()); |
| 204 EXPECT_EQ(0, bubble_factory()->total_request_count()); | 373 EXPECT_EQ(0, bubble_factory()->total_request_count()); |
| 205 | 374 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 221 // Bubble requests should not be shown when the killswitch is on. | 390 // Bubble requests should not be shown when the killswitch is on. |
| 222 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, | 391 IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, |
| 223 KillSwitchNotifications) { | 392 KillSwitchNotifications) { |
| 224 ASSERT_TRUE(embedded_test_server()->Start()); | 393 ASSERT_TRUE(embedded_test_server()->Start()); |
| 225 | 394 |
| 226 ui_test_utils::NavigateToURL( | 395 ui_test_utils::NavigateToURL( |
| 227 browser(), | 396 browser(), |
| 228 embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); | 397 embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); |
| 229 | 398 |
| 230 // Now enable the notifications killswitch. | 399 // Now enable the notifications killswitch. |
| 231 EnableKillSwitch(content::PermissionType::NOTIFICATIONS); | 400 EnableKillSwitch(PermissionType::NOTIFICATIONS); |
| 232 content::WebContents* web_contents = | 401 content::WebContents* web_contents = |
| 233 browser()->tab_strip_model()->GetActiveWebContents(); | 402 browser()->tab_strip_model()->GetActiveWebContents(); |
| 234 | 403 |
| 235 std::string result; | 404 std::string result; |
| 236 EXPECT_TRUE(content::ExecuteScriptAndExtractString( | 405 EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
| 237 web_contents, "requestNotification();", &result)); | 406 web_contents, "requestNotification();", &result)); |
| 238 EXPECT_EQ("denied", result); | 407 EXPECT_EQ("denied", result); |
| 239 EXPECT_EQ(0, bubble_factory()->show_count()); | 408 EXPECT_EQ(0, bubble_factory()->show_count()); |
| 240 EXPECT_EQ(0, bubble_factory()->total_request_count()); | 409 EXPECT_EQ(0, bubble_factory()->total_request_count()); |
| 241 | 410 |
| 242 // Disable the trial. | 411 // Disable the trial. |
| 243 variations::testing::ClearAllVariationParams(); | 412 variations::testing::ClearAllVariationParams(); |
| 244 | 413 |
| 245 EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); | 414 EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); |
| 246 bubble_factory()->WaitForPermissionBubble(); | 415 bubble_factory()->WaitForPermissionBubble(); |
| 247 EXPECT_EQ(1, bubble_factory()->show_count()); | 416 EXPECT_EQ(1, bubble_factory()->show_count()); |
| 248 EXPECT_EQ(1, bubble_factory()->total_request_count()); | 417 EXPECT_EQ(1, bubble_factory()->total_request_count()); |
| 249 } | 418 } |
| 250 | 419 |
| 251 } // anonymous namespace | 420 } // anonymous namespace |
| OLD | NEW |