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 | |
36 | namespace TestWebKitAPI { |
37 | |
38 | static bool didCrash; |
39 | static bool wasPrompted; |
40 | |
41 | static 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 | |
65 | static void checkUserMediaPermissionCallback(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionCheckRef permissionRequest, const void*) |
66 | { |
67 | WKUserMediaPermissionCheckSetUserMediaAccessInfo(permissionRequest, WKStringCreateWithUTF8CString("0x123456789" ), false); |
68 | } |
69 | |
70 | TEST(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 | |
99 | static 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 | |
106 | TEST(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 | |
160 | static bool didReceiveMessage; |
161 | static void didFinishNavigation(WKPageRef, WKNavigationRef, WKTypeRef, const void*) |
162 | { |
163 | didReceiveMessage = true; |
164 | } |
165 | |
166 | TEST(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 | |