1/*
2 * Copyright (C) 2014 Igalia S.L
3 * Copyright (C) 2016 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#include "config.h"
21
22#if WK_HAVE_C_SPI
23
24#if ENABLE(MEDIA_STREAM)
25#include "PlatformUtilities.h"
26#include "PlatformWebView.h"
27#include "Test.h"
28#include <WebKit/WKPagePrivate.h>
29#include <WebKit/WKPreferencesRef.h>
30#include <WebKit/WKPreferencesRefPrivate.h>
31#include <WebKit/WKRetainPtr.h>
32#include <WebKit/WKUserMediaPermissionCheck.h>
33#include <string.h>
34#include <vector>
35
36namespace TestWebKitAPI {
37
38static bool didCrash;
39static bool wasPrompted;
40
41static void decidePolicyForUserMediaPermissionRequestCallBack(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionRequestRef permissionRequest, const void* /* clientInfo */)
42{
43 WKRetainPtr<WKArrayRef> audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(permissionRequest);
44 WKRetainPtr<WKArrayRef> videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(permissionRequest);
45
46 if (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get())) {
47 WKRetainPtr<WKStringRef> videoDeviceUID;
48 if (WKArrayGetSize(videoDeviceUIDs.get()))
49 videoDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0));
50 else
51 videoDeviceUID = WKStringCreateWithUTF8CString("");
52
53 WKRetainPtr<WKStringRef> audioDeviceUID;
54 if (WKArrayGetSize(audioDeviceUIDs.get()))
55 audioDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(audioDeviceUIDs.get(), 0));
56 else
57 audioDeviceUID = WKStringCreateWithUTF8CString("");
58
59 WKUserMediaPermissionRequestAllow(permissionRequest, audioDeviceUID.get(), videoDeviceUID.get());
60 }
61
62 wasPrompted = true;
63}
64
65static void checkUserMediaPermissionCallback(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionCheckRef permissionRequest, const void*)
66{
67 WKUserMediaPermissionCheckSetUserMediaAccessInfo(permissionRequest, WKStringCreateWithUTF8CString("0x123456789"), false);
68}
69
70TEST(WebKit, UserMediaBasic)
71{
72 auto context = adoptWK(WKContextCreateWithConfiguration(nullptr));
73
74 WKRetainPtr<WKPageGroupRef> pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(Util::toWK("GetUserMedia").get()));
75 WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup.get());
76 WKPreferencesSetMediaDevicesEnabled(preferences, true);
77 WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
78 WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
79 WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
80
81 WKPageUIClientV6 uiClient;
82 memset(&uiClient, 0, sizeof(uiClient));
83 uiClient.base.version = 6;
84 uiClient.decidePolicyForUserMediaPermissionRequest = decidePolicyForUserMediaPermissionRequestCallBack;
85 uiClient.checkUserMediaPermissionForOrigin = checkUserMediaPermissionCallback;
86
87 PlatformWebView webView(context.get(), pageGroup.get());
88 WKPageSetPageUIClient(webView.page(), &uiClient.base);
89
90 wasPrompted = false;
91 auto url = adoptWK(Util::createURLForResource("getUserMedia", "html"));
92 ASSERT(url.get());
93
94 WKPageLoadURL(webView.page(), url.get());
95
96 Util::run(&wasPrompted);
97}
98
99static void didCrashCallback(WKPageRef, const void*)
100{
101 didCrash = true;
102 // Set wasPrompted to true to speed things up, we know the test failed.
103 wasPrompted = true;
104}
105
106TEST(WebKit, OnDeviceChangeCrash)
107{
108 auto context = adoptWK(WKContextCreateWithConfiguration(nullptr));
109
110 WKRetainPtr<WKPageGroupRef> pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(Util::toWK("GetUserMedia").get()));
111 WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup.get());
112 WKPreferencesSetMediaDevicesEnabled(preferences, true);
113 WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
114 WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
115 WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
116
117 WKPageUIClientV6 uiClient;
118 memset(&uiClient, 0, sizeof(uiClient));
119 uiClient.base.version = 6;
120 uiClient.decidePolicyForUserMediaPermissionRequest = decidePolicyForUserMediaPermissionRequestCallBack;
121 uiClient.checkUserMediaPermissionForOrigin = checkUserMediaPermissionCallback;
122
123 PlatformWebView webView(context.get(), pageGroup.get());
124 WKPageSetPageUIClient(webView.page(), &uiClient.base);
125
126 // Load a page registering ondevicechange handler.
127 auto url = adoptWK(Util::createURLForResource("ondevicechange", "html"));
128 ASSERT(url.get());
129
130 WKPageLoadURL(webView.page(), url.get());
131
132 // Load a second page in same process.
133 PlatformWebView webView2(webView.page());
134 WKPageSetPageUIClient(webView2.page(), &uiClient.base);
135 WKPageNavigationClientV0 navigationClient;
136 memset(&navigationClient, 0, sizeof(navigationClient));
137 navigationClient.base.version = 0;
138 navigationClient.webProcessDidCrash = didCrashCallback;
139 WKPageSetPageNavigationClient(webView2.page(), &navigationClient.base);
140
141 wasPrompted = false;
142 url = adoptWK(Util::createURLForResource("getUserMedia", "html"));
143 WKPageLoadURL(webView2.page(), url.get());
144 Util::run(&wasPrompted);
145 EXPECT_EQ(WKPageGetProcessIdentifier(webView.page()), WKPageGetProcessIdentifier(webView2.page()));
146
147 didCrash = false;
148
149 // Close first page.
150 WKPageClose(webView.page());
151
152 wasPrompted = false;
153 url = adoptWK(Util::createURLForResource("getUserMedia", "html"));
154 WKPageLoadURL(webView2.page(), url.get());
155 Util::run(&wasPrompted);
156 // Verify pages process did not crash.
157 EXPECT_TRUE(!didCrash);
158}
159
160static bool didReceiveMessage;
161static void didFinishNavigation(WKPageRef, WKNavigationRef, WKTypeRef, const void*)
162{
163 didReceiveMessage = true;
164}
165
166TEST(WebKit, EnumerateDevicesCrash)
167{
168 auto context = adoptWK(WKContextCreateWithConfiguration(nullptr));
169
170 WKRetainPtr<WKPageGroupRef> pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(Util::toWK("GetUserMedia").get()));
171 WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup.get());
172 WKPreferencesSetMediaDevicesEnabled(preferences, true);
173 WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
174 WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
175 WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
176
177 WKPageUIClientV6 uiClient;
178 // We want uiClient.checkUserMediaPermissionForOrigin to be null.
179 memset(&uiClient, 0, sizeof(uiClient));
180 uiClient.base.version = 6;
181
182 WKPageNavigationClientV3 loaderClient;
183 memset(&loaderClient, 0, sizeof(loaderClient));
184 loaderClient.base.version = 3;
185 loaderClient.didFinishNavigation = didFinishNavigation;
186
187 PlatformWebView webView(context.get(), pageGroup.get());
188 WKPageSetPageUIClient(webView.page(), &uiClient.base);
189 WKPageSetPageNavigationClient(webView.page(), &loaderClient.base);
190
191 // Load a page doing enumerateDevices.
192 didReceiveMessage = false;
193 auto url = adoptWK(Util::createURLForResource("getUserMedia", "html"));
194 WKPageLoadURL(webView.page(), url.get());
195 Util::run(&didReceiveMessage);
196}
197
198} // namespace TestWebKitAPI
199
200#endif // ENABLE(MEDIA_STREAM)
201
202#endif // WK_HAVE_C_SPI
203
204