Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/camera/camera_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
## NEXT
## 0.3.5+4

* Fixes a `TypeError` in `availableCameras()` caused by browsers (e.g. Firefox) returning
an invalid `facingMode` capability value instead of the expected `DOMString` sequence.
* Updates minimum supported SDK version to Flutter 3.38/Dart 3.10.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above this line, there should be a new line explaining what this change is doing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have made an update to it.


## 0.3.5+3

* Fixes camera initialization failure on Safari by fixing a null check operator error using
a nullable getter and null safe practices.
a nullable getter and null-safe practices.

## 0.3.5+2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,60 @@ void main() {
expect(facingMode, equals('environment'));
});

testWidgets('returns null '
'when the facing mode setting is empty and '
'the first facingMode capability is not a JavaScript string', (
WidgetTester tester,
) async {
mockVideoTrack.getSettings = () {
return web.MediaTrackSettings(facingMode: '');
}.toJS;
mockVideoTrack.getCapabilities = () {
return createJSInteropWrapper(FakeMediaTrackCapabilities())
as web.MediaTrackCapabilities;
}.toJS;

when(
jsUtil.hasProperty(videoTrack, 'getCapabilities'.toJS),
).thenReturn(true);
when(
jsUtil.getProperty(any, 'facingMode'.toJS),
).thenReturn(<JSAny>[true.toJS].toJS);

final String? facingMode = cameraService.getFacingModeForVideoTrack(
videoTrack,
);

expect(facingMode, isNull);
});

testWidgets('returns null '
'when the facing mode setting is empty and '
'the facingMode capability is not a JavaScript array', (
WidgetTester tester,
) async {
mockVideoTrack.getSettings = () {
return web.MediaTrackSettings(facingMode: '');
}.toJS;
mockVideoTrack.getCapabilities = () {
return createJSInteropWrapper(FakeMediaTrackCapabilities())
as web.MediaTrackCapabilities;
}.toJS;

when(
jsUtil.hasProperty(videoTrack, 'getCapabilities'.toJS),
).thenReturn(true);
when(
jsUtil.getProperty(any, 'facingMode'.toJS),
).thenReturn(true.toJS);

final String? facingMode = cameraService.getFacingModeForVideoTrack(
videoTrack,
);

expect(facingMode, isNull);
});

testWidgets('returns null '
'when the facing mode setting '
'and capabilities are empty', (WidgetTester tester) async {
Expand Down
35 changes: 23 additions & 12 deletions packages/camera/camera_web/lib/src/camera_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,20 +196,31 @@ class CameraService {
final web.MediaTrackCapabilities videoTrackCapabilities = videoTrack.getCapabilities();

// A list of facing mode capabilities as
// the camera may support multiple facing modes.
final List<String> facingModeCapabilities =
videoTrackCapabilities.facingModeNullable?.toDart
.map((JSString e) => e.toDart)
.toList() ??
<String>[];

if (facingModeCapabilities.isNotEmpty) {
final String facingModeCapability = facingModeCapabilities.first;
return facingModeCapability;
} else {
// Return null if there are no facing mode capabilities.
//The camera may support multiple facing modes.
// Some browsers (e.g., Firefox) do not conform to the MediaTrackCapabilities
// spec and may return `facingMode` as a non-array value (e.g., an empty string,
// a plain object, or a boolean) Rather than the expected DOMString sequence.
// We use jsUtil.getProperty to safely read the raw JS value, then explicitly
// validate it is a JSArray before accessing its elements to prevent a TypeError.

final JSAny? facingModeCapabilities = jsUtil.getProperty(
videoTrackCapabilities,
'facingMode'.toJS,
);
if (facingModeCapabilities == null ||
!facingModeCapabilities.isA<JSArray>()) {
return null;
}

final List<JSAny?> facingModes =
(facingModeCapabilities as JSArray).toDart;

if (facingModes.isNotEmpty && facingModes.first.isA<JSString>()) {
return (facingModes.first! as JSString).toDart;
}

// Return null if there are no facing mode capabilities.
return null;
}

return facingMode;
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: camera_web
description: A Flutter plugin for getting information about and controlling the camera on Web.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_web
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.3.5+3
version: 0.3.5+4

environment:
sdk: ^3.10.0
Expand Down