blob: 50585ba51c671a264621c5d0ecfe560fb2172673 [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async' show Zone, runZoned;
import 'package:meta/meta.dart';
import 'os_kind.dart';
import 'osid_unknown.dart'
if (dart.library.io) 'osid_io.dart'
if (dart.library.html) 'osid_html.dart';
/// The name and version of an operating system.
final class OperatingSystem {
// The recognized OS identifier strings.
/// The operating system ID string for Linux.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const androidId = RecognizedOS.androidId;
/// The operating system ID string for browsers.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const browserId = RecognizedOS.browserId;
/// The operating system ID string for Fuchsia.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const fuchsiaId = RecognizedOS.fuchsiaId;
/// The operating system ID string for iOS.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const iOSId = RecognizedOS.iOSId;
/// The operating system ID string for Linux.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const linuxId = RecognizedOS.linuxId;
/// The operating system ID string for macOS.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const macOSId = RecognizedOS.macOSId;
/// The operating system ID string for Windows.
///
/// Compare against [id] or the `operatingSystem` of `os_detect.dart`,
/// or use as argument to [OperatingSystem.new].
static const windowsId = RecognizedOS.windowsId;
/// The current operating system ID.
///
/// Defaults to what information is available
/// from known platform specific libraries,
/// but can be overridden using functionality from the
/// `osid_override.dart` library.
@pragma('vm:try-inline')
static OperatingSystem get current =>
Zone.current[#_os] as OperatingSystem? ?? platformOS;
/// A string representing the operating system or platform.
String get id => _osId.id;
// Operating system ID object.
final RecognizedOS _osId;
/// A string representing the version of the operating system or platform.
///
/// May be empty if no version is known or available.
final String version;
/// Creates a new operating system object for testing.
///
/// Can be used with [overrideOperatingSystem] to selectively
/// change the value returned by [current].
///
/// **Notice:** Using this constructor may reduce the efficiency
/// of compilers recognizing code that isn't needed when compiling
/// for a particular platform (aka. "tree-shaking" of unreachable code).
// Uses chained conditionals to allow back-ends to constant fold when they
// know what `id` is, which they'd usually know for a specific operation.
// That can avoid retaining *all* the subclasses of `OS`.
@visibleForTesting
@pragma('vm:prefer-inline')
OperatingSystem(String id, String version)
: this._(
id == linuxId
? const LinuxOS()
: id == macOSId
? const MacOS()
: id == windowsId
? const WindowsOS()
: id == androidId
? const AndroidOS()
: id == iOSId
? const IOS()
: id == fuchsiaId
? const FuchsiaOS()
: id == browserId
? const BrowserOS()
: UnknownOS(id),
version,
);
/// Used by platforms which know the ID object.
const OperatingSystem._(this._osId, this.version);
/// Whether the operating system is a version of
/// [Linux](https://en.wikipedia.org/wiki/Linux).
///
/// Identified by [id] being the string `linux`.
///
/// This value is `false` if the operating system is a specialized
/// version of Linux that identifies itself by a different name,
/// for example Android (see [isAndroid]).
bool get isLinux => _osId is LinuxOS;
/// Whether the operating system is a version of
/// [macOS](https://en.wikipedia.org/wiki/MacOS).
///
/// Identified by [id] being the string `macos`.
bool get isMacOS => _osId is MacOS;
/// Whether the operating system is a version of
/// [Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft_Windows).
///
/// Identified by [id] being the string `windows`.
bool get isWindows => _osId is WindowsOS;
/// Whether the operating system is a version of
/// [Android](https://en.wikipedia.org/wiki/Android_%28operating_system%29).
///
/// Identified by [id] being the string `android`.
bool get isAndroid => _osId is AndroidOS;
/// Whether the operating system is a version of
/// [iOS](https://en.wikipedia.org/wiki/IOS).
///
/// Identified by [id] being the string `ios`.
bool get isIOS => _osId is IOS;
/// Whether the operating system is a version of
/// [Fuchsia](https://en.wikipedia.org/wiki/Google_Fuchsia).
///
/// Identified by [id] being the string `fuchsia`.
bool get isFuchsia => _osId is FuchsiaOS;
/// Whether running in a web browser.
///
/// Identified by [id] being the string `browser`.
///
/// If so, the [version] is the string made available
/// through `window.navigator.appVersion`.
bool get isBrowser => _osId is BrowserOS;
}
/// Run [body] in a zone with platform overrides.
///
/// Overrides [OperatingSystem.current] with the supplied [operatingSystem]
/// value while running in a new zone, and then runs [body] in that zone.
///
/// This override affects the `operatingSystem` and `version`
/// exported by `package:osid/osid.dart`.
R overrideOperatingSystem<R>(
OperatingSystem operatingSystem,
R Function() body,
) =>
runZoned(body, zoneValues: {#_os: operatingSystem});
// Exposes the `OperatingSystem._` constructor to the conditionally imported
// libraries. Not exported by `../override.dart'.
final class OperatingSystemInternal extends OperatingSystem {
const OperatingSystemInternal(super.id, super.version) : super._();
}