Changeset 237770 in webkit
- Timestamp:
- Nov 3, 2018 6:30:30 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r237766 r237770 1 2018-11-03 Eric Carlson <eric.carlson@apple.com> 2 3 [MediaStream] enumerateDevices should not expose devices that are not available to getUserMedia 4 https://bugs.webkit.org/show_bug.cgi?id=191177 5 <rdar://problem/45747873> 6 7 Reviewed by Jer Noble. 8 9 * http/tests/media/media-stream/enumerate-devices-iframe-allow-attribute-expected.txt: Added. 10 * http/tests/media/media-stream/enumerate-devices-iframe-allow-attribute.html: Added. 11 * http/tests/media/media-stream/resources/enumerate-devices-iframe.html: Added. 12 * http/tests/ssl/media-stream/get-user-media-different-host-expected.txt: Rebased for updated logging. 13 * http/tests/ssl/media-stream/get-user-media-nested-expected.txt: Ditto. 14 1 15 2018-11-02 Justin Michaud <justin_michaud@apple.com> 2 16 -
trunk/LayoutTests/http/tests/ssl/media-stream/get-user-media-different-host-expected.txt
r231450 r237770 1 CONSOLE MESSAGE: line 52: The top-level frame has prevented a document with a different security origin to callgetUserMedia.1 CONSOLE MESSAGE: line 52: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 2 2 Tests that getUserMedia fails when the top level document and iframe do not have the same domain. 3 3 -
trunk/LayoutTests/http/tests/ssl/media-stream/get-user-media-nested-expected.txt
r231450 r237770 1 CONSOLE MESSAGE: line 52: The top-level frame has prevented a document with a different security origin to callgetUserMedia.1 CONSOLE MESSAGE: line 52: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 2 2 Tests that getUserMedia fails when the top level document and iframe do not have the same domain. 3 3 -
trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-default-feature-policy.https-expected.txt
r235484 r237770 1 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.2 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.3 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.4 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.5 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.6 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.7 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin to callgetUserMedia.1 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 2 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 3 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 4 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 5 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 6 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 7 CONSOLE MESSAGE: line 16: The top-level frame has prevented a document with a different security origin from calling getUserMedia. 8 8 9 9 -
trunk/Source/WebCore/ChangeLog
r237766 r237770 1 2018-11-03 Eric Carlson <eric.carlson@apple.com> 2 3 [MediaStream] enumerateDevices should not expose devices that are not available to getUserMedia 4 https://bugs.webkit.org/show_bug.cgi?id=191177 5 <rdar://problem/45747873> 6 7 Reviewed by Jer Noble. 8 9 Test: http/tests/media/media-stream/enumerate-devices-iframe-allow-attribute.html 10 11 * Modules/mediastream/MediaDevicesRequest.cpp: 12 (WebCore::MediaDevicesRequest::start): Only expose devices that are available to gUM. 13 14 * Modules/mediastream/UserMediaController.cpp: 15 (WebCore::isSecure): Moved from UserMediaRequest.cpp. 16 (WebCore::isAllowedToUse): Ditto. 17 (WebCore::UserMediaController::canCallGetUserMedia): Modified from UserMediaRequest.cpp. 18 (WebCore::UserMediaController::logGetUserMediaDenial): Log reason for denial. 19 * Modules/mediastream/UserMediaController.h: 20 21 * Modules/mediastream/UserMediaRequest.cpp: 22 (WebCore::UserMediaRequest::start): Use UserMediaController::canCallGetUserMedia. 23 (WebCore::isSecure): Deleted. 24 (WebCore::isAllowedToUse): Deleted. 25 (WebCore::canCallGetUserMedia): Deleted. 26 1 27 2018-11-02 Justin Michaud <justin_michaud@apple.com> 2 28 -
trunk/Source/WebCore/Modules/mediastream/MediaDevicesRequest.cpp
r237643 r237770 104 104 void MediaDevicesRequest::start() 105 105 { 106 auto& document = downcast<Document>(*scriptExecutionContext()); 107 auto* controller = UserMediaController::from(document.page()); 108 if (!controller) { 109 callOnMainThread([protectedThis = makeRef(*this)]() { 110 protectedThis->m_promise.resolve({ }); 111 }); 112 113 return; 114 } 115 116 auto microphoneAccess = controller->canCallGetUserMedia(document, true, false); 117 auto cameraAccess = controller->canCallGetUserMedia(document, false, true); 118 bool canAccessMicrophone = microphoneAccess == UserMediaController::GetUserMediaAccess::CanCall; 119 bool canAccessCamera = cameraAccess == UserMediaController::GetUserMediaAccess::CanCall; 120 if (!canAccessMicrophone && !canAccessCamera) { 121 controller->logGetUserMediaDenial(document, !canAccessMicrophone ? microphoneAccess : cameraAccess, UserMediaController::BlockedCaller::EnumerateDevices); 122 callOnMainThread([protectedThis = makeRef(*this)]() { 123 protectedThis->m_promise.resolve({ }); 124 }); 125 126 return; 127 } 128 106 129 // This lambda keeps |this| alive until the request completes or is canceled. 107 auto completion = [this, protectedThis = makeRef(*this) ] (const Vector<CaptureDevice>& captureDevices, const String& deviceIdentifierHashSalt, bool originHasPersistentAccess) mutable {130 auto completion = [this, protectedThis = makeRef(*this), canAccessMicrophone, canAccessCamera] (const Vector<CaptureDevice>& captureDevices, const String& deviceIdentifierHashSalt, bool originHasPersistentAccess) mutable { 108 131 109 132 m_enumerationRequest = nullptr; … … 118 141 bool revealIdsAndLabels = originHasPersistentAccess || document.hasHadCaptureMediaStreamTrack(); 119 142 for (auto& deviceInfo : captureDevices) { 143 if (!canAccessMicrophone && deviceInfo.type() == CaptureDevice::DeviceType::Microphone) 144 continue; 145 if (!canAccessCamera && deviceInfo.type() == CaptureDevice::DeviceType::Camera) 146 continue; 147 120 148 auto label = emptyString(); 121 149 auto id = emptyString(); … … 141 169 }; 142 170 143 m_enumerationRequest = MediaDevicesEnumerationRequest::create( *downcast<Document>(scriptExecutionContext()), WTFMove(completion));171 m_enumerationRequest = MediaDevicesEnumerationRequest::create(document, WTFMove(completion)); 144 172 m_enumerationRequest->start(); 145 173 } -
trunk/Source/WebCore/Modules/mediastream/UserMediaController.cpp
r218601 r237770 1 1 /* 2 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * Copyright (C) 2013-2018 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 28 29 #if ENABLE(MEDIA_STREAM) 29 30 31 #include "DOMWindow.h" 32 #include "DeprecatedGlobalSettings.h" 33 #include "Document.h" 34 #include "DocumentLoader.h" 35 #include "Frame.h" 36 #include "HTMLIFrameElement.h" 37 #include "HTMLParserIdioms.h" 38 #include "SchemeRegistry.h" 30 39 #include "UserMediaRequest.h" 31 40 … … 52 61 } 53 62 63 static bool isSecure(DocumentLoader& documentLoader) 64 { 65 auto& response = documentLoader.response(); 66 if (SecurityOrigin::isLocalHostOrLoopbackIPAddress(documentLoader.response().url().host())) 67 return true; 68 return SchemeRegistry::shouldTreatURLSchemeAsSecure(response.url().protocol().toStringWithoutCopying()) 69 && response.certificateInfo() 70 && !response.certificateInfo()->containsNonRootSHA1SignedCertificate(); 71 } 72 73 static bool isAllowedToUse(Document& document, Document& topDocument, bool requiresAudio, bool requiresVideo) 74 { 75 if (&document == &topDocument) 76 return true; 77 78 auto* parentDocument = document.parentDocument(); 79 if (!parentDocument) 80 return false; 81 82 if (document.securityOrigin().isSameSchemeHostPort(parentDocument->securityOrigin())) 83 return true; 84 85 auto* element = document.ownerElement(); 86 ASSERT(element); 87 if (!element) 88 return false; 89 90 if (!is<HTMLIFrameElement>(*element)) 91 return false; 92 auto& allow = downcast<HTMLIFrameElement>(*element).allow(); 93 94 bool allowCameraAccess = false; 95 bool allowMicrophoneAccess = false; 96 for (auto allowItem : StringView { allow }.split(';')) { 97 auto item = allowItem.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace<UChar>); 98 if (!allowCameraAccess && item == "camera") 99 allowCameraAccess = true; 100 else if (!allowMicrophoneAccess && item == "microphone") 101 allowMicrophoneAccess = true; 102 } 103 return (allowCameraAccess || !requiresVideo) && (allowMicrophoneAccess || !requiresAudio); 104 } 105 106 UserMediaController::GetUserMediaAccess UserMediaController::canCallGetUserMedia(Document& document, bool wantsAudio, bool wantsVideo) 107 { 108 ASSERT(wantsAudio || wantsVideo); 109 110 bool requiresSecureConnection = DeprecatedGlobalSettings::mediaCaptureRequiresSecureConnection(); 111 auto& documentLoader = *document.loader(); 112 if (requiresSecureConnection && !isSecure(documentLoader)) 113 return GetUserMediaAccess::InsecureDocument; 114 115 auto& topDocument = document.topDocument(); 116 if (&document != &topDocument) { 117 for (auto* ancestorDocument = &document; ancestorDocument != &topDocument; ancestorDocument = ancestorDocument->parentDocument()) { 118 if (requiresSecureConnection && !isSecure(*ancestorDocument->loader())) 119 return GetUserMediaAccess::InsecureParent; 120 121 if (!isAllowedToUse(*ancestorDocument, topDocument, wantsAudio, wantsVideo)) 122 return GetUserMediaAccess::BlockedByParent; 123 } 124 } 125 126 return GetUserMediaAccess::CanCall; 127 } 128 129 void UserMediaController::logGetUserMediaDenial(Document& document, GetUserMediaAccess access, BlockedCaller caller) 130 { 131 auto& domWindow = *document.domWindow(); 132 const char* callerName = caller == BlockedCaller::GetUserMedia ? "getUserMedia" : "enumerateDevices"; 133 switch (access) { 134 case UserMediaController::GetUserMediaAccess::InsecureDocument: 135 domWindow.printErrorMessage(makeString("Trying to call ", callerName, " from an insecure document.")); 136 break; 137 case UserMediaController::GetUserMediaAccess::InsecureParent: 138 domWindow.printErrorMessage(makeString("Trying to call ", callerName, " from a document with an insecure parent frame.")); 139 break; 140 case UserMediaController::GetUserMediaAccess::BlockedByParent: 141 domWindow.printErrorMessage(makeString("The top-level frame has prevented a document with a different security origin from calling ", callerName, ".")); 142 break; 143 case UserMediaController::GetUserMediaAccess::CanCall: 144 break; 145 } 146 } 147 54 148 } // namespace WebCore 55 149 -
trunk/Source/WebCore/Modules/mediastream/UserMediaController.h
r235086 r237770 52 52 void removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken); 53 53 54 enum class GetUserMediaAccess { 55 CanCall, 56 InsecureDocument, 57 InsecureParent, 58 BlockedByParent 59 }; 60 GetUserMediaAccess canCallGetUserMedia(Document&, bool wantsAudio, bool wantsVideo); 61 62 enum class BlockedCaller { 63 GetUserMedia, 64 EnumerateDevices 65 }; 66 void logGetUserMediaDenial(Document&, GetUserMediaAccess, BlockedCaller); 67 54 68 WEBCORE_EXPORT static const char* supplementName(); 55 69 static UserMediaController* from(Page* page) { return static_cast<UserMediaController*>(Supplement<Page>::from(page, supplementName())); } -
trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
r236877 r237770 2 2 * Copyright (C) 2011 Ericsson AB. All rights reserved. 3 3 * Copyright (C) 2012 Google Inc. All rights reserved. 4 * Copyright (C) 2013-201 7Apple Inc. All rights reserved.4 * Copyright (C) 2013-2018 Apple Inc. All rights reserved. 5 5 * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). 6 6 * … … 37 37 #if ENABLE(MEDIA_STREAM) 38 38 39 #include "CaptureDeviceManager.h"40 #include "DeprecatedGlobalSettings.h"41 39 #include "Document.h" 42 #include "DocumentLoader.h"43 40 #include "Frame.h" 44 #include "HTMLIFrameElement.h"45 #include "HTMLParserIdioms.h"46 41 #include "JSMediaStream.h" 47 42 #include "JSOverconstrainedError.h" … … 83 78 return nullptr; 84 79 return &m_scriptExecutionContext->topOrigin(); 85 }86 87 static bool isSecure(DocumentLoader& documentLoader)88 {89 auto& response = documentLoader.response();90 if (SecurityOrigin::isLocalHostOrLoopbackIPAddress(documentLoader.response().url().host()))91 return true;92 return SchemeRegistry::shouldTreatURLSchemeAsSecure(response.url().protocol().toStringWithoutCopying())93 && response.certificateInfo()94 && !response.certificateInfo()->containsNonRootSHA1SignedCertificate();95 }96 97 static bool isAllowedToUse(Document& document, Document& topDocument, bool requiresAudio, bool requiresVideo)98 {99 if (&document == &topDocument)100 return true;101 102 auto* parentDocument = document.parentDocument();103 if (!parentDocument)104 return false;105 106 if (document.securityOrigin().isSameSchemeHostPort(parentDocument->securityOrigin()))107 return true;108 109 auto* element = document.ownerElement();110 ASSERT(element);111 if (!element)112 return false;113 114 if (!is<HTMLIFrameElement>(*element))115 return false;116 auto& allow = downcast<HTMLIFrameElement>(*element).allow();117 118 bool allowCameraAccess = false;119 bool allowMicrophoneAccess = false;120 for (auto allowItem : StringView { allow }.split(';')) {121 auto item = allowItem.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace<UChar>);122 if (!allowCameraAccess && item == "camera")123 allowCameraAccess = true;124 else if (!allowMicrophoneAccess && item == "microphone")125 allowMicrophoneAccess = true;126 }127 return (allowCameraAccess || !requiresVideo) && (allowMicrophoneAccess || !requiresAudio);128 }129 130 static bool canCallGetUserMedia(Document& document, bool wantsAudio, bool wantsVideo, String& errorMessage)131 {132 ASSERT(wantsAudio || wantsVideo);133 134 bool requiresSecureConnection = DeprecatedGlobalSettings::mediaCaptureRequiresSecureConnection();135 auto& documentLoader = *document.loader();136 if (requiresSecureConnection && !isSecure(documentLoader)) {137 errorMessage = "Trying to call getUserMedia from an insecure document.";138 return false;139 }140 141 auto& topDocument = document.topDocument();142 if (&document != &topDocument) {143 for (auto* ancestorDocument = &document; ancestorDocument != &topDocument; ancestorDocument = ancestorDocument->parentDocument()) {144 if (requiresSecureConnection && !isSecure(*ancestorDocument->loader())) {145 errorMessage = "Trying to call getUserMedia from a document with an insecure parent frame.";146 return false;147 }148 149 if (!isAllowedToUse(*ancestorDocument, topDocument, wantsAudio, wantsVideo)) {150 errorMessage = "The top-level frame has prevented a document with a different security origin to call getUserMedia.";151 return false;152 }153 }154 }155 156 return true;157 80 } 158 81 … … 267 190 // 6.10 Permission Failure: Reject p with a new DOMException object whose name attribute has 268 191 // the value NotAllowedError. 269 String errorMessage;270 if ( !canCallGetUserMedia(document, m_request.audioConstraints.isValid, m_request.videoConstraints.isValid, errorMessage)) {192 auto access = controller->canCallGetUserMedia(document, m_request.audioConstraints.isValid, m_request.videoConstraints.isValid); 193 if (access != UserMediaController::GetUserMediaAccess::CanCall) { 271 194 deny(MediaAccessDenialReason::PermissionDenied); 272 document.domWindow()->printErrorMessage(errorMessage);195 controller->logGetUserMediaDenial(document, access, UserMediaController::BlockedCaller::GetUserMedia); 273 196 return; 274 197 }
Note: See TracChangeset
for help on using the changeset viewer.