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/Deque.h>
28#include <wtf/HashMap.h>
29#include <wtf/LoggerHelper.h>
30#include <wtf/RunLoop.h>
31#include <wtf/Seconds.h>
32#include <wtf/WeakPtr.h>
33
34namespace WebCore {
35class CaptureDevice;
36struct MediaConstraints;
37struct MediaStreamRequest;
38class SecurityOrigin;
39};
40
41namespace WebKit {
42
43class WebPageProxy;
44
45class UserMediaPermissionRequestManagerProxy
46 : public CanMakeWeakPtr<UserMediaPermissionRequestManagerProxy>
47#if !RELEASE_LOG_DISABLED
48 , private LoggerHelper
49#endif
50{
51public:
52 explicit UserMediaPermissionRequestManagerProxy(WebPageProxy&);
53 ~UserMediaPermissionRequestManagerProxy();
54
55 WebPageProxy& page() const { return m_page; }
56
57#if ENABLE(MEDIA_STREAM)
58 static void forEach(const WTF::Function<void(UserMediaPermissionRequestManagerProxy&)>&);
59#endif
60
61 void invalidatePendingRequests();
62
63 void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, WebCore::MediaStreamRequest&&);
64
65 void resetAccess(uint64_t mainFrameID);
66 void viewIsBecomingVisible();
67
68 void grantRequest(UserMediaPermissionRequestProxy&);
69 void denyRequest(UserMediaPermissionRequestProxy&, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason, const String& invalidConstraint = { });
70
71 void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin);
72
73 void stopCapture();
74 void scheduleNextRejection();
75 void rejectionTimerFired();
76 void clearCachedState();
77 void captureDevicesChanged();
78
79 void captureStateChanged(WebCore::MediaProducer::MediaStateFlags oldState, WebCore::MediaProducer::MediaStateFlags newState);
80 void syncWithWebCorePrefs() const;
81
82 enum class RequestAction {
83 Deny,
84 Grant,
85 Prompt
86 };
87
88private:
89#if !RELEASE_LOG_DISABLED
90 const Logger& logger() const final;
91 const void* logIdentifier() const final { return m_logIdentifier; }
92 const char* logClassName() const override { return "UserMediaPermissionRequestManagerProxy"; }
93 WTFLogChannel& logChannel() const final;
94#endif
95
96 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&&);
97#if ENABLE(MEDIA_STREAM)
98 void finishGrantingRequest(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 using PermissionInfo = UserMediaPermissionCheckProxy::PermissionInfo;
104 void getUserMediaPermissionInfo(uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, CompletionHandler<void(PermissionInfo)>&&);
105
106 RequestAction getRequestAction(const UserMediaPermissionRequestProxy&);
107
108 bool wasGrantedVideoOrAudioAccess(uint64_t, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin);
109
110 Vector<WebCore::CaptureDevice> computeFilteredDeviceList(bool revealIdsAndLabels, const String& deviceIDHashSalt);
111
112 void processUserMediaPermissionRequest();
113 void processUserMediaPermissionInvalidRequest(const String& invalidConstraint);
114 void processUserMediaPermissionValidRequest(Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, String&& deviceIdentifierHashSalt);
115 void startProcessingUserMediaPermissionRequest(Ref<UserMediaPermissionRequestProxy>&&);
116#endif
117
118 void watchdogTimerFired();
119
120 void processNextUserMediaRequestIfNeeded();
121
122 RefPtr<UserMediaPermissionRequestProxy> m_currentUserMediaRequest;
123 Deque<Ref<UserMediaPermissionRequestProxy>> m_pendingUserMediaRequests;
124 HashSet<uint64_t> m_pendingDeviceRequests;
125
126 WebPageProxy& m_page;
127
128 RunLoop::Timer<UserMediaPermissionRequestManagerProxy> m_rejectionTimer;
129 Deque<Ref<UserMediaPermissionRequestProxy>> m_pendingRejections;
130
131 Vector<Ref<UserMediaPermissionRequestProxy>> m_pregrantedRequests;
132 Vector<Ref<UserMediaPermissionRequestProxy>> m_grantedRequests;
133
134 struct DeniedRequest {
135 uint64_t mainFrameID;
136 Ref<WebCore::SecurityOrigin> userMediaDocumentOrigin;
137 Ref<WebCore::SecurityOrigin> topLevelDocumentOrigin;
138 bool isAudioDenied;
139 bool isVideoDenied;
140 bool isScreenCaptureDenied;
141 };
142 Vector<DeniedRequest> m_deniedRequests;
143
144 WebCore::MediaProducer::MediaStateFlags m_captureState { WebCore::MediaProducer::IsNotPlaying };
145 RunLoop::Timer<UserMediaPermissionRequestManagerProxy> m_watchdogTimer;
146 Seconds m_currentWatchdogInterval;
147#if !RELEASE_LOG_DISABLED
148 Ref<const Logger> m_logger;
149 const void* m_logIdentifier;
150#endif
151 bool m_hasFilteredDeviceList { false };
152 uint64_t m_hasPendingCapture { 0 };
153};
154
155String convertEnumerationToString(UserMediaPermissionRequestManagerProxy::RequestAction);
156
157} // namespace WebKit
158
159#if ENABLE(MEDIA_STREAM)
160namespace WTF {
161
162template<typename Type>
163struct LogArgument;
164
165template <>
166struct LogArgument<WebKit::UserMediaPermissionRequestManagerProxy::RequestAction> {
167 static String toString(const WebKit::UserMediaPermissionRequestManagerProxy::RequestAction type)
168 {
169 return convertEnumerationToString(type);
170 }
171};
172
173}; // namespace WTF
174#endif
175