Skip to content

Commit b2978d1

Browse files
committed
Chrome third party cookies fallback
1 parent a2a32e7 commit b2978d1

File tree

8 files changed

+446
-40
lines changed

8 files changed

+446
-40
lines changed

src/pages/Camera/utils/cameraUtils.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getContextRefs } from "../context/CameraContext";
22
import { setPipMode } from "./uiState";
3+
import { getUserMediaWithFallback } from "../../utils/mediaDeviceFallback";
34

45
const CLOUD_FEATURES_ENABLED =
56
process.env.SCREENITY_ENABLE_CLOUD_FEATURES === "true";
@@ -41,7 +42,47 @@ export const getCameraStream = async (
4142
}
4243

4344
try {
44-
const stream = await navigator.mediaDevices.getUserMedia(constraints);
45+
const desiredVideoId = constraints?.video?.deviceId?.exact || null;
46+
let desiredVideoLabel = "";
47+
48+
if (desiredVideoId) {
49+
const { defaultVideoInputLabel, videoinput, videoInput } =
50+
await chrome.storage.local.get([
51+
"defaultVideoInputLabel",
52+
"videoinput",
53+
"videoInput",
54+
]);
55+
const storedDevices = Array.isArray(videoinput)
56+
? videoinput
57+
: Array.isArray(videoInput)
58+
? videoInput
59+
: [];
60+
desiredVideoLabel =
61+
defaultVideoInputLabel ||
62+
storedDevices.find((device) => device.deviceId === desiredVideoId)
63+
?.label ||
64+
"";
65+
}
66+
67+
const stream = await getUserMediaWithFallback({
68+
constraints,
69+
fallbacks:
70+
desiredVideoId && desiredVideoLabel
71+
? [
72+
{
73+
kind: "videoinput",
74+
desiredDeviceId: desiredVideoId,
75+
desiredLabel: desiredVideoLabel,
76+
onResolved: (resolvedId) => {
77+
chrome.storage.local.set({
78+
defaultVideoInput: resolvedId,
79+
defaultVideoInputLabel: desiredVideoLabel,
80+
});
81+
},
82+
},
83+
]
84+
: [],
85+
});
4586

4687
streamRef.current = stream;
4788

src/pages/CloudRecorder/CloudRecorder.jsx

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getBitrates, getResolutionForQuality } from "./recorderConfig";
55
import BunnyTusUploader from "./bunnyTusUploader";
66
import localforage from "localforage";
77
import { createVideoProject } from "./createVideoProject";
8+
import { getUserMediaWithFallback } from "../utils/mediaDeviceFallback";
89

910
localforage.config({
1011
driver: localforage.INDEXEDDB,
@@ -1847,12 +1848,41 @@ const CloudRecorder = () => {
18471848
};
18481849

18491850
const startAudioStream = async (id) => {
1851+
const useExact = id && id !== "none";
18501852
const audioStreamOptions = {
1851-
audio: { deviceId: id ? { exact: id } : undefined },
1853+
audio: useExact ? { deviceId: { exact: id } } : true,
18521854
};
18531855

18541856
try {
1855-
return await navigator.mediaDevices.getUserMedia(audioStreamOptions);
1857+
const { defaultAudioInputLabel, audioinput } =
1858+
await chrome.storage.local.get([
1859+
"defaultAudioInputLabel",
1860+
"audioinput",
1861+
]);
1862+
const desiredLabel =
1863+
defaultAudioInputLabel ||
1864+
audioinput?.find((device) => device.deviceId === id)?.label ||
1865+
"";
1866+
1867+
return await getUserMediaWithFallback({
1868+
constraints: audioStreamOptions,
1869+
fallbacks:
1870+
useExact && desiredLabel
1871+
? [
1872+
{
1873+
kind: "audioinput",
1874+
desiredDeviceId: id,
1875+
desiredLabel,
1876+
onResolved: (resolvedId) => {
1877+
chrome.storage.local.set({
1878+
defaultAudioInput: resolvedId,
1879+
defaultAudioInputLabel: desiredLabel,
1880+
});
1881+
},
1882+
},
1883+
]
1884+
: [],
1885+
});
18561886
} catch (err) {
18571887
console.warn(
18581888
"⚠️ Failed to access audio with deviceId, trying fallback:",
@@ -1878,6 +1908,41 @@ const CloudRecorder = () => {
18781908
}
18791909
};
18801910

1911+
const getVideoStreamWithFallback = async (constraints, deviceId) => {
1912+
if (!deviceId || deviceId === "none") {
1913+
return navigator.mediaDevices.getUserMedia(constraints);
1914+
}
1915+
const { defaultVideoInputLabel, videoinput } =
1916+
await chrome.storage.local.get([
1917+
"defaultVideoInputLabel",
1918+
"videoinput",
1919+
]);
1920+
const desiredLabel =
1921+
defaultVideoInputLabel ||
1922+
videoinput?.find((device) => device.deviceId === deviceId)?.label ||
1923+
"";
1924+
1925+
return getUserMediaWithFallback({
1926+
constraints,
1927+
fallbacks:
1928+
deviceId && desiredLabel
1929+
? [
1930+
{
1931+
kind: "videoinput",
1932+
desiredDeviceId: deviceId,
1933+
desiredLabel,
1934+
onResolved: (resolvedId) => {
1935+
chrome.storage.local.set({
1936+
defaultVideoInput: resolvedId,
1937+
defaultVideoInputLabel: desiredLabel,
1938+
});
1939+
},
1940+
},
1941+
]
1942+
: [],
1943+
});
1944+
};
1945+
18811946
const startStream = async (data, id, permissions, permissions2) => {
18821947
// Defaulting quality for now
18831948
//const { qualityValue } = await chrome.storage.local.get(["qualityValue"]);
@@ -1963,8 +2028,9 @@ const CloudRecorder = () => {
19632028
};
19642029

19652030
try {
1966-
cameraStream.current = await navigator.mediaDevices.getUserMedia(
1967-
cameraConstraints
2031+
cameraStream.current = await getVideoStreamWithFallback(
2032+
cameraConstraints,
2033+
defaultVideoInput
19682034
);
19692035
} catch (err) {
19702036
console.warn(
@@ -2114,8 +2180,9 @@ const CloudRecorder = () => {
21142180
};
21152181

21162182
try {
2117-
cameraStream.current = await navigator.mediaDevices.getUserMedia(
2118-
cameraConstraints
2183+
cameraStream.current = await getVideoStreamWithFallback(
2184+
cameraConstraints,
2185+
defaultVideoInput
21192186
);
21202187
} catch (err) {
21212188
console.warn(

src/pages/Content/context/ContentState.jsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,37 @@ const ContentState = (props) => {
614614
microphonePermission: microphonePermission,
615615
}));
616616

617+
const audioInputById = Array.isArray(audioInput)
618+
? Object.fromEntries(
619+
audioInput.map((device) => [device.deviceId, device.label])
620+
)
621+
: {};
622+
const videoInputById = Array.isArray(videoInput)
623+
? Object.fromEntries(
624+
videoInput.map((device) => [device.deviceId, device.label])
625+
)
626+
: {};
627+
628+
const defaultAudioInputLabel =
629+
audioInputById[contentStateRef.current.defaultAudioInput] || "";
630+
const defaultVideoInputLabel =
631+
videoInputById[contentStateRef.current.defaultVideoInput] || "";
632+
633+
setContentState((prevContentState) => ({
634+
...prevContentState,
635+
defaultAudioInputLabel:
636+
defaultAudioInputLabel || prevContentState.defaultAudioInputLabel,
637+
defaultVideoInputLabel:
638+
defaultVideoInputLabel || prevContentState.defaultVideoInputLabel,
639+
}));
640+
641+
chrome.storage.local.set({
642+
defaultAudioInputLabel:
643+
defaultAudioInputLabel || contentStateRef.current.defaultAudioInputLabel,
644+
defaultVideoInputLabel:
645+
defaultVideoInputLabel || contentStateRef.current.defaultVideoInputLabel,
646+
});
647+
617648
chrome.runtime.sendMessage({
618649
type: "switch-camera",
619650
id: contentStateRef.current.defaultVideoInput,
@@ -627,21 +658,25 @@ const ContentState = (props) => {
627658
setContentState((prevContentState) => ({
628659
...prevContentState,
629660
defaultAudioInput: audioInput[0].deviceId,
661+
defaultAudioInputLabel: audioInput[0].label || "",
630662
micActive: true,
631663
}));
632664
chrome.storage.local.set({
633665
defaultAudioInput: audioInput[0].deviceId,
666+
defaultAudioInputLabel: audioInput[0].label || "",
634667
micActive: true,
635668
});
636669
}
637670
if (videoInput.length > 0) {
638671
setContentState((prevContentState) => ({
639672
...prevContentState,
640673
defaultVideoInput: videoInput[0].deviceId,
674+
defaultVideoInputLabel: videoInput[0].label || "",
641675
cameraActive: true,
642676
}));
643677
chrome.storage.local.set({
644678
defaultVideoInput: videoInput[0].deviceId,
679+
defaultVideoInputLabel: videoInput[0].label || "",
645680
cameraActive: true,
646681
});
647682
}
@@ -737,6 +772,8 @@ const ContentState = (props) => {
737772
setDevices: false,
738773
defaultAudioInput: "none",
739774
defaultVideoInput: "none",
775+
defaultAudioInputLabel: "",
776+
defaultVideoInputLabel: "",
740777
cameraActive: false,
741778
micActive: false,
742779
sortBy: "newest",

src/pages/Content/context/utils/updateFromStorage.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export const updateFromStorage = (check = true, id = null) => {
2222
"videoInput",
2323
"defaultAudioInput",
2424
"defaultVideoInput",
25+
"defaultAudioInputLabel",
26+
"defaultVideoInputLabel",
2527
"cameraDimensions",
2628
"cameraFlipped",
2729
"cameraActive",
@@ -111,6 +113,16 @@ export const updateFromStorage = (check = true, id = null) => {
111113
result.defaultVideoInput !== null
112114
? result.defaultVideoInput
113115
: prevContentState.defaultVideoInput,
116+
defaultAudioInputLabel:
117+
result.defaultAudioInputLabel !== undefined &&
118+
result.defaultAudioInputLabel !== null
119+
? result.defaultAudioInputLabel
120+
: prevContentState.defaultAudioInputLabel,
121+
defaultVideoInputLabel:
122+
result.defaultVideoInputLabel !== undefined &&
123+
result.defaultVideoInputLabel !== null
124+
? result.defaultVideoInputLabel
125+
: prevContentState.defaultVideoInputLabel,
114126
cameraDimensions:
115127
result.cameraDimensions !== undefined &&
116128
result.cameraDimensions !== null

src/pages/Content/popup/components/Dropdown.jsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,24 +169,26 @@ const Dropdown = (props) => {
169169
});
170170
setLabel(chrome.i18n.getMessage("noCameraDropdownLabel"));
171171
} else {
172+
const selectedLabel =
173+
contentState.videoInput.find(
174+
(device) => device.deviceId === newValue
175+
)?.label || "";
172176
setContentState((prevContentState) => ({
173177
...prevContentState,
174178
defaultVideoInput: newValue,
179+
defaultVideoInputLabel: selectedLabel,
175180
cameraActive: true,
176181
}));
177182
chrome.storage.local.set({
178183
defaultVideoInput: newValue,
184+
defaultVideoInputLabel: selectedLabel,
179185
cameraActive: true,
180186
});
181187
chrome.runtime.sendMessage({
182188
type: "switch-camera",
183189
id: newValue,
184190
});
185-
setLabel(
186-
contentState.videoInput.find(
187-
(device) => device.deviceId === newValue
188-
).label
189-
);
191+
setLabel(selectedLabel);
190192
}
191193
} else {
192194
if (newValue === "none") {
@@ -199,20 +201,22 @@ const Dropdown = (props) => {
199201
});
200202
setLabel(chrome.i18n.getMessage("noMicrophoneDropdownLabel"));
201203
} else {
204+
const selectedLabel =
205+
contentState.audioInput.find(
206+
(device) => device.deviceId === newValue
207+
)?.label || "";
202208
setContentState((prevContentState) => ({
203209
...prevContentState,
204210
defaultAudioInput: newValue,
211+
defaultAudioInputLabel: selectedLabel,
205212
micActive: true,
206213
}));
207214
chrome.storage.local.set({
208215
defaultAudioInput: newValue,
216+
defaultAudioInputLabel: selectedLabel,
209217
micActive: true,
210218
});
211-
setLabel(
212-
contentState.audioInput.find(
213-
(device) => device.deviceId === newValue
214-
).label
215-
);
219+
setLabel(selectedLabel);
216220
}
217221
}
218222
}}

0 commit comments

Comments
 (0)