diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/WebProcess/MediaStream | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebKit2/WebProcess/MediaStream')
4 files changed, 448 insertions, 0 deletions
diff --git a/Source/WebKit2/WebProcess/MediaStream/MediaDeviceSandboxExtensions.cpp b/Source/WebKit2/WebProcess/MediaStream/MediaDeviceSandboxExtensions.cpp new file mode 100644 index 000000000..2a4fb525c --- /dev/null +++ b/Source/WebKit2/WebProcess/MediaStream/MediaDeviceSandboxExtensions.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MediaDeviceSandboxExtensions.h" + +#if ENABLE(MEDIA_STREAM) + +#include "WebCoreArgumentCoders.h" + +namespace WebKit { + +MediaDeviceSandboxExtensions::MediaDeviceSandboxExtensions(Vector<String> ids, SandboxExtension::HandleArray&& handles) + : m_ids(ids) + , m_handles(WTFMove(handles)) +{ + ASSERT_WITH_SECURITY_IMPLICATION(m_ids.size() == m_handles.size()); +} + +void MediaDeviceSandboxExtensions::encode(IPC::Encoder& encoder) const +{ + encoder << m_ids; + m_handles.encode(encoder); +} + +bool MediaDeviceSandboxExtensions::decode(IPC::Decoder& decoder, MediaDeviceSandboxExtensions& result) +{ + if (!decoder.decode(result.m_ids)) + return false; + + if (!SandboxExtension::HandleArray::decode(decoder, result.m_handles)) + return false; + + return true; +} + +std::pair<String, RefPtr<SandboxExtension>> MediaDeviceSandboxExtensions::operator[](size_t i) +{ + ASSERT_WITH_SECURITY_IMPLICATION(m_ids.size() == m_handles.size()); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_ids.size()); + return { m_ids[i], SandboxExtension::create(m_handles[i]) }; +} + +const std::pair<String, RefPtr<SandboxExtension>> MediaDeviceSandboxExtensions::operator[](size_t i) const +{ + ASSERT_WITH_SECURITY_IMPLICATION(m_ids.size() == m_handles.size()); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_ids.size()); + return { m_ids[i], SandboxExtension::create(m_handles[i]) }; +} + +size_t MediaDeviceSandboxExtensions::size() const +{ + return m_ids.size(); +} + +} // namespace WebKit + +#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebKit2/WebProcess/MediaStream/MediaDeviceSandboxExtensions.h b/Source/WebKit2/WebProcess/MediaStream/MediaDeviceSandboxExtensions.h new file mode 100644 index 000000000..a270f4e1e --- /dev/null +++ b/Source/WebKit2/WebProcess/MediaStream/MediaDeviceSandboxExtensions.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(MEDIA_STREAM) + +#include "SandboxExtension.h" +#include <wtf/Noncopyable.h> +#include <wtf/RefPtr.h> + +namespace WebKit { + +class MediaDeviceSandboxExtensions { + WTF_MAKE_NONCOPYABLE(MediaDeviceSandboxExtensions); +public: + MediaDeviceSandboxExtensions() + { + } + + MediaDeviceSandboxExtensions(Vector<String> ids, SandboxExtension::HandleArray&& handles); + + std::pair<String, RefPtr<SandboxExtension>> operator[](size_t i); + const std::pair<String, RefPtr<SandboxExtension>> operator[](size_t i) const; + size_t size() const; + + void encode(IPC::Encoder&) const; + static bool decode(IPC::Decoder&, MediaDeviceSandboxExtensions&); + +private: + Vector<String> m_ids; + SandboxExtension::HandleArray m_handles; +}; + +} // namespace WebKit + +#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp b/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp new file mode 100644 index 000000000..7f11dc7a3 --- /dev/null +++ b/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "UserMediaPermissionRequestManager.h" + +#if ENABLE(MEDIA_STREAM) + +#include "WebFrame.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include <WebCore/CaptureDevice.h> +#include <WebCore/Document.h> +#include <WebCore/Frame.h> +#include <WebCore/FrameLoader.h> +#include <WebCore/MediaConstraintsImpl.h> +#include <WebCore/SecurityOrigin.h> +#include <WebCore/SecurityOriginData.h> + +using namespace WebCore; + +namespace WebKit { + +using namespace WebCore; + +static uint64_t generateRequestID() +{ + static uint64_t uniqueRequestID = 1; + return uniqueRequestID++; +} + +UserMediaPermissionRequestManager::UserMediaPermissionRequestManager(WebPage& page) + : m_page(page) +{ +} + +UserMediaPermissionRequestManager::~UserMediaPermissionRequestManager() +{ + for (auto& sandboxExtension : m_userMediaDeviceSandboxExtensions) + sandboxExtension.value->revoke(); +} + +void UserMediaPermissionRequestManager::startUserMediaRequest(UserMediaRequest& request) +{ + Document* document = request.document(); + Frame* frame = document ? document->frame() : nullptr; + + if (!frame || !document->page()) { + request.deny(UserMediaRequest::OtherFailure, emptyString()); + return; + } + + if (document->page()->canStartMedia()) { + sendUserMediaRequest(request); + return; + } + + auto& pendingRequests = m_blockedRequests.add(document, Vector<RefPtr<UserMediaRequest>>()).iterator->value; + if (pendingRequests.isEmpty()) + document->addMediaCanStartListener(this); + pendingRequests.append(&request); +} + +void UserMediaPermissionRequestManager::sendUserMediaRequest(UserMediaRequest& request) +{ + Document* document = request.document(); + Frame* frame = document ? document->frame() : nullptr; + + if (!frame) { + request.deny(UserMediaRequest::OtherFailure, emptyString()); + return; + } + + uint64_t requestID = generateRequestID(); + m_idToUserMediaRequestMap.add(requestID, &request); + m_userMediaRequestToIDMap.add(&request, requestID); + + WebFrame* webFrame = WebFrame::fromCoreFrame(*frame); + ASSERT(webFrame); + + SecurityOrigin* topLevelDocumentOrigin = request.topLevelDocumentOrigin(); + String topLevelDocumentOriginString = topLevelDocumentOrigin ? SecurityOriginData::fromSecurityOrigin(*topLevelDocumentOrigin).databaseIdentifier() : emptyString(); + m_page.send(Messages::WebPageProxy::RequestUserMediaPermissionForFrame(requestID, webFrame->frameID(), SecurityOriginData::fromSecurityOrigin(*request.userMediaDocumentOrigin()).databaseIdentifier(), topLevelDocumentOriginString, request.audioConstraints().data(), request.videoConstraints().data())); +} + +void UserMediaPermissionRequestManager::cancelUserMediaRequest(UserMediaRequest& request) +{ + uint64_t requestID = m_userMediaRequestToIDMap.take(&request); + if (!requestID) + return; + m_idToUserMediaRequestMap.remove(requestID); + removeMediaRequestFromMaps(request); +} + +void UserMediaPermissionRequestManager::mediaCanStart(Document& document) +{ + auto pendingRequests = m_blockedRequests.take(&document); + while (!pendingRequests.isEmpty()) { + if (!document.page()->canStartMedia()) { + m_blockedRequests.add(&document, pendingRequests); + document.addMediaCanStartListener(this); + break; + } + + sendUserMediaRequest(*pendingRequests.takeLast()); + } +} + +void UserMediaPermissionRequestManager::removeMediaRequestFromMaps(UserMediaRequest& request) +{ + Document* document = request.document(); + if (!document) + return; + + auto pendingRequests = m_blockedRequests.take(document); + for (auto& pendingRequest : pendingRequests) { + if (&request != pendingRequest.get()) + continue; + + if (pendingRequests.isEmpty()) + request.document()->removeMediaCanStartListener(this); + else + m_blockedRequests.add(request.document(), pendingRequests); + break; + } + + m_userMediaRequestToIDMap.remove(&request); +} + +void UserMediaPermissionRequestManager::userMediaAccessWasGranted(uint64_t requestID, const String& audioDeviceUID, const String& videoDeviceUID) +{ + auto request = m_idToUserMediaRequestMap.take(requestID); + if (!request) + return; + removeMediaRequestFromMaps(*request); + + request->allow(audioDeviceUID, videoDeviceUID); +} + +void UserMediaPermissionRequestManager::userMediaAccessWasDenied(uint64_t requestID, WebCore::UserMediaRequest::MediaAccessDenialReason reason, const String& invalidConstraint) +{ + auto request = m_idToUserMediaRequestMap.take(requestID); + if (!request) + return; + removeMediaRequestFromMaps(*request); + + request->deny(reason, invalidConstraint); +} + +void UserMediaPermissionRequestManager::enumerateMediaDevices(MediaDevicesEnumerationRequest& request) +{ + auto* document = downcast<Document>(request.scriptExecutionContext()); + auto* frame = document ? document->frame() : nullptr; + + if (!frame) { + request.setDeviceInfo(Vector<CaptureDevice>(), emptyString(), false); + return; + } + + uint64_t requestID = generateRequestID(); + m_idToMediaDevicesEnumerationRequestMap.add(requestID, &request); + m_mediaDevicesEnumerationRequestToIDMap.add(&request, requestID); + + WebFrame* webFrame = WebFrame::fromCoreFrame(*frame); + ASSERT(webFrame); + + SecurityOrigin* topLevelDocumentOrigin = request.topLevelDocumentOrigin(); + String topLevelDocumentOriginString = topLevelDocumentOrigin ? SecurityOriginData::fromSecurityOrigin(*topLevelDocumentOrigin).databaseIdentifier() : emptyString(); + m_page.send(Messages::WebPageProxy::EnumerateMediaDevicesForFrame(requestID, webFrame->frameID(), SecurityOriginData::fromSecurityOrigin(*request.userMediaDocumentOrigin()).databaseIdentifier(), topLevelDocumentOriginString)); +} + +void UserMediaPermissionRequestManager::cancelMediaDevicesEnumeration(WebCore::MediaDevicesEnumerationRequest& request) +{ + uint64_t requestID = m_mediaDevicesEnumerationRequestToIDMap.take(&request); + if (!requestID) + return; + m_idToMediaDevicesEnumerationRequestMap.remove(requestID); +} + +void UserMediaPermissionRequestManager::didCompleteMediaDeviceEnumeration(uint64_t requestID, const Vector<CaptureDevice>& deviceList, const String& mediaDeviceIdentifierHashSalt, bool hasPersistentAccess) +{ + RefPtr<MediaDevicesEnumerationRequest> request = m_idToMediaDevicesEnumerationRequestMap.take(requestID); + if (!request) + return; + m_mediaDevicesEnumerationRequestToIDMap.remove(request); + + request->setDeviceInfo(deviceList, mediaDeviceIdentifierHashSalt, hasPersistentAccess); +} + +void UserMediaPermissionRequestManager::grantUserMediaDeviceSandboxExtensions(const MediaDeviceSandboxExtensions& extensions) +{ + for (size_t i = 0; i < extensions.size(); i++) { + auto& extension = extensions[i]; + extension.second->consume(); + m_userMediaDeviceSandboxExtensions.add(extension.first, extension.second.copyRef()); + } +} + +void UserMediaPermissionRequestManager::revokeUserMediaDeviceSandboxExtensions(const Vector<String>& extensionIDs) +{ + for (const auto& extensionID : extensionIDs) { + auto extension = m_userMediaDeviceSandboxExtensions.take(extensionID); + if (extension) + extension->revoke(); + } +} + +} // namespace WebKit + +#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h b/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h new file mode 100644 index 000000000..e8a96c253 --- /dev/null +++ b/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Igalia S.L. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef UserMediaPermissionRequestManager_h +#define UserMediaPermissionRequestManager_h + +#if ENABLE(MEDIA_STREAM) + +#include "MediaDeviceSandboxExtensions.h" +#include "SandboxExtension.h" +#include <WebCore/MediaCanStartListener.h> +#include <WebCore/MediaConstraints.h> +#include <WebCore/MediaDevicesEnumerationRequest.h> +#include <WebCore/UserMediaClient.h> +#include <WebCore/UserMediaRequest.h> +#include <wtf/HashMap.h> +#include <wtf/Ref.h> +#include <wtf/RefPtr.h> + +namespace WebKit { + +class WebPage; + +class UserMediaPermissionRequestManager + : private WebCore::MediaCanStartListener { +public: + explicit UserMediaPermissionRequestManager(WebPage&); + ~UserMediaPermissionRequestManager(); + + void startUserMediaRequest(WebCore::UserMediaRequest&); + void cancelUserMediaRequest(WebCore::UserMediaRequest&); + void userMediaAccessWasGranted(uint64_t, const String& audioDeviceUID, const String& videoDeviceUID); + void userMediaAccessWasDenied(uint64_t, WebCore::UserMediaRequest::MediaAccessDenialReason, const String&); + + void enumerateMediaDevices(WebCore::MediaDevicesEnumerationRequest&); + void cancelMediaDevicesEnumeration(WebCore::MediaDevicesEnumerationRequest&); + void didCompleteMediaDeviceEnumeration(uint64_t, const Vector<WebCore::CaptureDevice>& deviceList, const String& deviceIdentifierHashSalt, bool originHasPersistentAccess); + + void grantUserMediaDeviceSandboxExtensions(const MediaDeviceSandboxExtensions&); + void revokeUserMediaDeviceSandboxExtensions(const Vector<String>&); + +private: + void sendUserMediaRequest(WebCore::UserMediaRequest&); + + // WebCore::MediaCanStartListener + void mediaCanStart(WebCore::Document&) override; + + void removeMediaRequestFromMaps(WebCore::UserMediaRequest&); + + WebPage& m_page; + + HashMap<uint64_t, RefPtr<WebCore::UserMediaRequest>> m_idToUserMediaRequestMap; + HashMap<RefPtr<WebCore::UserMediaRequest>, uint64_t> m_userMediaRequestToIDMap; + + HashMap<uint64_t, RefPtr<WebCore::MediaDevicesEnumerationRequest>> m_idToMediaDevicesEnumerationRequestMap; + HashMap<RefPtr<WebCore::MediaDevicesEnumerationRequest>, uint64_t> m_mediaDevicesEnumerationRequestToIDMap; + + HashMap<String, RefPtr<SandboxExtension>> m_userMediaDeviceSandboxExtensions; + + HashMap<RefPtr<WebCore::Document>, Vector<RefPtr<WebCore::UserMediaRequest>>> m_blockedRequests; +}; + +} // namespace WebKit + +#endif // ENABLE(MEDIA_STREAM) + +#endif // UserMediaPermissionRequestManager_h |