1/*
2 * Copyright (C) 2014 Igalia S.L.
3 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#pragma once
21
22#include "UserMediaPermissionCheckProxy.h"
23#include "UserMediaPermissionRequestProxy.h"
24#include <WebCore/MediaProducer.h>
25#include <WebCore/SecurityOrigin.h>
26#include <wtf/CompletionHandler.h>
27#include <wtf/HashMap.h>
28#include <wtf/LoggerHelper.h>
29#include <wtf/RunLoop.h>
30#include <wtf/Seconds.h>
31#include <wtf/WeakPtr.h>
32
33namespace WebCore {
34class CaptureDevice;
35struct MediaConstraints;
36struct MediaStreamRequest;
37class SecurityOrigin;
38};
39
40namespace WebKit {
41
42class WebPageProxy;
43
44class UserMediaPermissionRequestManagerProxy
45 : public CanMakeWeakPtr<UserMediaPermissionRequestManagerProxy>
46#if !RELEASE_LOG_DISABLED
47 , private LoggerHelper
48#endif
49{
50public:
51 explicit UserMediaPermissionRequestManagerProxy(WebPageProxy&);
52 ~UserMediaPermissionRequestManagerProxy();
53
54 WebPageProxy& page() const { return m_page; }
55
56#if ENABLE(MEDIA_STREAM)
57 static void forEach(const WTF::Function<void(UserMediaPermissionRequestManagerProxy&)>&);
58#endif
59
60 void invalidatePendingRequests();
61
62 void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, WebCore::MediaStreamRequest&&);
63
64 void resetAccess(uint64_t mainFrameID);
65 void viewIsBecomingVisible();
66
67 void userMediaAccessWasGranted(uint64_t, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice);
68 void userMediaAccessWasDenied(uint64_t, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason);
69
70 void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin);
71
72 void stopCapture();
73 void scheduleNextRejection();
74 void rejectionTimerFired();
75 void clearCachedState();
76 void captureDevicesChanged();
77
78 void captureStateChanged(WebCore::MediaProducer::MediaStateFlags oldState, WebCore::MediaProducer::MediaStateFlags newState);
79 void syncWithWebCorePrefs() const;
80
81 enum class RequestAction {
82 Deny,
83 Grant,
84 Prompt
85 };
86
87private:
88#if !RELEASE_LOG_DISABLED
89 const Logger& logger() const final;
90 const void* logIdentifier() const final { return m_logIdentifier; }
91 const char* logClassName() const override { return "UserMediaPermissionRequestManagerProxy"; }
92 WTFLogChannel& logChannel() const final;
93#endif
94
95 Ref<UserMediaPermissionRequestProxy> createPermissionRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, WebCore::MediaStreamRequest&&);
96 void denyRequest(uint64_t userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason, const String& invalidConstraint);
97#if ENABLE(MEDIA_STREAM)
98 bool grantAccess(const UserMediaPermissionRequestProxy&);
99
100 const UserMediaPermissionRequestProxy* searchForGrantedRequest(uint64_t frameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo) const;
101 bool wasRequestDenied(uint64_t mainFrameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo, bool needsScreenCapture);
102
103 void getUserMediaPermissionInfo(uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, CompletionHandler<void(Optional<bool>)>&&);
104
105 RequestAction getRequestAction(const UserMediaPermissionRequestProxy&);
106
107 bool wasGrantedVideoOrAudioAccess(uint64_t, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin);
108
109 Vector<WebCore::CaptureDevice> computeFilteredDeviceList(bool revealIdsAndLabels, const String& deviceIDHashSalt);
110
111 void processUserMediaPermissionRequest(Ref<UserMediaPermissionRequestProxy>&&, bool hasPersistentAccess);
112 void processUserMediaPermissionInvalidRequest(const UserMediaPermissionRequestProxy&, const String& invalidConstraint);
113 void processUserMediaPermissionValidRequest(Ref<UserMediaPermissionRequestProxy>&&, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, String&& deviceIdentifierHashSalt);
114#endif
115
116 void watchdogTimerFired();
117
118 HashMap<uint64_t, RefPtr<UserMediaPermissionRequestProxy>> m_pendingUserMediaRequests;
119 HashSet<uint64_t> m_pendingDeviceRequests;
120
121 WebPageProxy& m_page;
122
123 RunLoop::Timer<UserMediaPermissionRequestManagerProxy> m_rejectionTimer;
124 Vector<uint64_t> m_pendingRejections;
125
126 Vector<Ref<UserMediaPermissionRequestProxy>> m_pregrantedRequests;
127 Vector<Ref<UserMediaPermissionRequestProxy>> m_grantedRequests;
128
129 struct DeniedRequest {
130 uint64_t mainFrameID;
131 Ref<WebCore::SecurityOrigin> userMediaDocumentOrigin;
132 Ref<WebCore::SecurityOrigin> topLevelDocumentOrigin;
133 bool isAudioDenied;
134 bool isVideoDenied;
135 bool isScreenCaptureDenied;
136 };
137 Vector<DeniedRequest> m_deniedRequests;
138
139 WebCore::MediaProducer::MediaStateFlags m_captureState { WebCore::MediaProducer::IsNotPlaying };
140 RunLoop::Timer<UserMediaPermissionRequestManagerProxy> m_watchdogTimer;
141 Seconds m_currentWatchdogInterval;
142#if !RELEASE_LOG_DISABLED
143 Ref<const Logger> m_logger;
144 const void* m_logIdentifier;
145#endif
146 bool m_hasFilteredDeviceList { false };
147 uint64_t m_hasPendingCapture { 0 };
148};
149
150String convertEnumerationToString(UserMediaPermissionRequestManagerProxy::RequestAction);
151
152} // namespace WebKit
153
154#if ENABLE(MEDIA_STREAM)
155namespace WTF {
156
157template<typename Type>
158struct LogArgument;
159
160template <>
161struct LogArgument<WebKit::UserMediaPermissionRequestManagerProxy::RequestAction> {
162 static String toString(const WebKit::UserMediaPermissionRequestManagerProxy::RequestAction type)
163 {
164 return convertEnumerationToString(type);
165 }
166};
167
168}; // namespace WTF
169#endif
170