Copyright © 2025 the Contributors to the Web Serial API Specification, published by the Web Platform Incubator Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
本仕様書は Web Platform Incubator Community Group により発行されました。これはW3C標準でもなく、W3C Standards Track上のものでもありません。 W3C Community Contributor License Agreement (CLA) の下では限定的なオプトアウトやその他の条件があることにご注意ください。 W3C Community and Business Groups について詳しくはリンクをご参照ください。
本仕様は作業中のドラフトです。全ての貢献を歓迎します。本仕様について議論する場合はGitHub Issuesを推奨します。
Serial インターフェイス
WebIDL[Exposed=(DedicatedWorker, Window), SecureContext]
interface Serial : EventTarget {
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
Promise<sequence<SerialPort>> getPorts();
[Exposed=Window] Promise<SerialPort> requestPort(optional SerialPortRequestOptions options = {});
};
requestPort()メソッドの手順は以下のとおりです:
serial"
ポリシー制御機能でない場合、
reject
promiseに"SecurityError" DOMExceptionで返し、終了。
SecurityError" DOMExceptionで返し、終了。
filters"]が存在する場合、すべてのfilterについて以下を実行する:
bluetoothServiceClassId"]
が存在する場合:
usbVendorId"]
が存在する場合、
reject
promiseにTypeErrorで返し、終了。
usbProductId"]
が存在する場合、
reject
promiseにTypeErrorで返し、終了。
usbVendorId"]が存在しない場合、
reject
promiseにTypeErrorで返し、終了。
BluetoothServiceUUID
uuidごとに:
allowedBluetoothServiceClassIds"]
が存在し、そのリストにuuidが含まれている場合:
SerialPortとして生成。
SerialPortとして生成。
filters"]のいずれかのフィルターに
マッチするもののみ(あるいはフィルターがなければすべて)を選ばせるプロンプトを表示する。
NotFoundError" DOMException
で返し、以降中断。
SerialPortとして用意。
シリアルポートは、利用可能とは、有線の場合は物理的にシステムに接続されているポート、無線の場合はデバイスがシステムに登録されているポートを指します。
WebIDLdictionary SerialPortRequestOptions {
sequence<SerialPortFilter> filters;
sequence<BluetoothServiceUUID> allowedBluetoothServiceClassIds;
};
filters メンバー
allowedBluetoothServiceClassIds メンバー
BluetoothServiceUUID
型のBluetoothサービスクラスIDのリスト。BluetoothポートがカスタムサービスクラスIDを持つ場合は、このリストに含まれていない限り、ユーザーへの提示リストから除外されます。
WebIDLdictionary SerialPortFilter {
unsigned short usbVendorId;
unsigned short usbProductId;
BluetoothServiceUUID bluetoothServiceClassId;
};
usbVendorId メンバー
usbProductId メンバー
bluetoothServiceClassId メンバー
シリアルポートportがフィルターfilterにマッチする条件は以下です:
getInfo() コールの結果を得る。
bluetoothServiceClassId"]が
存在する場合:
bluetoothServiceClassId"]と等しければ、trueを返す。
usbVendorId"]が存在しない場合、trueを返す。
usbVendorId"]が
フィルターのusbVendorId値と等しくなければfalseを返す。
usbProductId"]が
存在しない場合はtrueを返す。
usbProductId"]が
フィルターのusbProductIdと等しくなければfalseを返す。
シリアルポートportは、シーケンス内の
SerialPortFilterのいずれかにマッチする条件は下記:
getPorts()メソッドの手順は以下の通りです:
"serial"というポリシー制御機能でない場合、
reject promiseに"SecurityError" DOMExceptionで返し、終了。
requestPort()の実行でサイトにアクセス許可を付与した利用可能なシリアルポートとする。
SerialPort一覧とする。
onconnectは
イベントハンドラーIDL属性であり、
connectイベントタイプ用です。
ondisconnectは
イベントハンドラーIDL属性であり、
disconnectイベントタイプ用です。
WebIDL[Exposed=(DedicatedWorker,Window), SecureContext]
interface SerialPort : EventTarget {
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
readonly attribute boolean connected;
readonly attribute ReadableStream readable;
readonly attribute WritableStream writable;
SerialPortInfo getInfo();
Promise<undefined> open(SerialOptions options);
Promise<undefined> setSignals(optional SerialOutputSignals signals = {});
Promise<SerialInputSignals> getSignals();
Promise<undefined> close();
Promise<undefined> forget();
};
このインターフェイスのメソッドは、通常非同期に完了し、シリアルポートタスクソース上で作業をキューします。
SerialPortの親を取得するアルゴリズムは、そのSerialインスタンスを返します。このインスタンスはSerialPortの
関連グローバルオブジェクトの
Navigator
オブジェクトのserialゲッターで返されるものと同じです。
SerialPortのインスタンスは、以下の表で説明される内部スロットを持ちます。
| 内部スロット | 初期値 | 説明(非規範的) |
|---|---|---|
| [[state]] |
"closed"
|
SerialPortの動作状態を追跡します
|
| [[bufferSize]] | undefined | 送受信でバッファするデータ量 |
| [[connected]] |
false
|
シリアルポートの論理的接続状態を示すフラグ |
| [[readable]] |
null
|
ポートからデータを受信するReadableStream
|
| [[readFatal]] |
false
|
ポートで重大な読み取りエラーが発生したことを示すフラグ |
| [[writable]] |
null
|
ポートへデータを送信するWritableStream
|
| [[writeFatal]] |
false
|
ポートで重大な書き込みエラーが発生したことを示すフラグ |
| [[pendingClosePromise]] |
null
|
Promise。readableやwritableのクローズ待機などに利用
|
onconnectはイベントハンドラーIDL属性です。
connectイベント型用です。
ユーザーがrequestPort()の呼び出しでサイトへのアクセスを許可したシリアルポートが
論理的に接続された場合、以下の手順を実行します:
SerialPortを用意する。
[[connected]]をtrueに設定。
connectをportで発火し、そのbubbles属性をtrueで初期化する。
シリアルポートは論理的に接続とは、有線シリアルポートの場合は物理的に接続されているとき、無線の場合はシステムが該当デバイスにアクティブ接続(例: Bluetooth L2CAPチャネルが開いている)を持っているときです。
ondisconnectはイベントハンドラーIDL属性であり、
disconnectイベント型用です。
ユーザーがrequestPort()の呼び出しでサイトへのアクセスを許可したシリアルポートが
論理的に接続でなくなった場合、以下の手順を実行します:
SerialPortを用意する。
[[connected]]をfalseに設定。
disconnectをportで発火し、そのbubbles属性をtrueで初期化する。
getInfo() メソッドの手順は以下の通りです:
usbVendorId"]
にデバイスのベンダーIDを設定。
usbProductId"]
にデバイスのプロダクトIDを設定。
bluetoothServiceClassId"]
にBluetoothサービスのサービスクラスUUIDを設定
WebIDLdictionary SerialPortInfo {
unsigned short usbVendorId;
unsigned short usbProductId;
BluetoothServiceUUID bluetoothServiceClassId;
};
usbVendorId メンバー
undefinedです。
usbProductId メンバー
undefinedです。
bluetoothServiceClassId メンバー
BluetoothServiceUUID
となります。それ以外の場合はundefinedです。
open() メソッドの手順は以下の通りです:
[[state]] が "closed" 以外なら、
promise を "InvalidStateError" DOMException で reject
し返す。
dataBits"] が 7
または 8 でなければ、
promise を TypeError で
reject し返す。
stopBits"] が 1
または 2 でなければ、
promise を TypeError で
reject し返す。
bufferSize"] が
0 なら、
promise を TypeError で
reject し返す。
bufferSize"] が
実装がサポートできる値より大きい場合も、 promise
を TypeError で
reject し返すことができる。
[[state]] を "opening" に設定する。
NetworkError"
DOMException
で返して、処理を中断する。
[[state]] を "opened" に設定する。
[[bufferSize]] を
options["bufferSize"] に設定する。
undefined にする。
WebIDLdictionary SerialOptions {
[EnforceRange] required unsigned long baudRate;
[EnforceRange] octet dataBits = 8;
[EnforceRange] octet stopBits = 1;
ParityType parity = "none";
[EnforceRange] unsigned long bufferSize = 255;
FlowControlType flowControl = "none";
};
baudRate メンバー
baudRate はこの
辞書で唯一必須なメンバーです。他の接続パラメータには一般的なデフォルトがありますが、接続する機器に応じて正しい値を検討・機器のドキュメントで確認することが重要です。多くは一般的な値ですが、標準化されたボーレートはありません。このパラメータを必須とすることで、仕様が任意のデフォルト値を選択した場合の混乱を防ぎます。
dataBits メンバー
stopBits メンバー
parity メンバー
bufferSize
メンバー
flowControl メンバー
WebIDLenum ParityType {
"none",
"even",
"odd"
};
none
even
odd
WebIDLenum FlowControlType {
"none",
"hardware"
};
none
hardware
connected ゲッターの手順は:
[[connected]] を返す。
readable ゲッターの手順は以下の通りです:
[[readable]] が null でなければ
this.[[readable]] を返す。
[[state]] が "opened" でなければ
null を返す。
[[readFatal]] が true なら
null を返す。
ReadableStream として生成。
[[readable]]。
[[readable]] の
current
BYOB request view が non-null なら desiredSize を当該 view の
byte
length に設定。
[[readable]] の
current
BYOB request view が non-null ならば、
write
で bytes を
this.[[readable]]
の current BYOB request view に書き込んだうえで
view をその view に設定。
Uint8Array
をbytesから生成。view を(this の
関連Realm
で)。
[[readable]] へ。
[[readable]]に
"BufferOverrunError" DOMException
で発生させ、handle closing the
readable stream の手順を実行。
BreakError"。
FramingError"。
ParityError"。
UnknownError"
DOMException
で発生し handle closing the readable stream の手順。
[[readFatal]] を
true に設定
[[readable]] に
"NetworkError"
DOMException
で発生。
undefined を返す。
undefined で。
[[bufferSize]] にする。
[[readable]] を stream に設定。
[[readable]] に null を設定。
[[writable]] が null かつ
this.[[pendingClosePromise]] が
null でなければ
resolve で
this.[[pendingClosePromise]] を
undefined で完了。
writable ゲッターの手順は以下の通りです:
[[writable]] が null でなければ
this.[[writable]] を返す。
[[state]] が "opened" でなければ
null を返す。
[[writeFatal]] が true なら
null を返す。
WritableStream
として作成。
BufferSource 型IDL値に
変換
できなければ、
TypeError
で
promise を reject、return。それ以外の場合はその結果を
source に保存。
undefined で完了。
UnknownError"
DOMException
で返す。
[[writeFatal]] を
true に
NetworkError"
DOMException
で返す。
undefined で。
undefined で。
[[bufferSize]]
を、それから
sizeAlgorithmはバイトカウントするアルゴリズムをセット。
[[writable]] を stream にセット。
[[writable]] を null に設定。
[[readable]] が null かつ
this.[[pendingClosePromise]] が
null でなければ
resolve で
this.[[pendingClosePromise]] を
undefined で完了。
setSignals() メソッドの手順は以下の通りです:
[[state]] が "opened" でなければ、
promise を "InvalidStateError" DOMException で reject
し、返す。
TypeError で
promise を reject し返す。
dataTerminalReady"]
が存在すれば、OSに「data terminal ready(DTR)」信号をアサート(true)またはディアサート(false)を指示。
requestToSend"] が
存在すれば、OSに「request to send(RTS)」信号をアサートまたはディアサートを指示。
break"]
があれば、OSに「break」信号のアサートまたはディアサートを指示。
NetworkError"
DOMException で
reject。
undefined で完了。
WebIDLdictionary SerialOutputSignals {
boolean dataTerminalReady;
boolean requestToSend;
boolean break;
};
dataTerminalReady
requestToSend
break
getSignals() メソッドの手順は以下の通りです:
[[state]] が "opened" でなければ
promise を "InvalidStateError" DOMException で reject
し返す。
NetworkError"
DOMException で
reject し、処理を中断。
true、それ以外は falseとする。
true、それ以外は
false
true、それ以外は
false
true、それ以外は
false
dataCarrierDetect"
→ dataCarrierDetect,
"clearToSend" →
clearToSend,
"ringIndicator" →
ringIndicator,
"dataSetReady" →
dataSetReady ]» として用意。
WebIDLdictionary SerialInputSignals {
required boolean dataCarrierDetect;
required boolean clearToSend;
required boolean ringIndicator;
required boolean dataSetReady;
};
dataCarrierDetect
メンバー
clearToSend
メンバー
ringIndicator
メンバー
dataSetReady
メンバー
close() メソッドの手順は以下の通りです:
[[state]] が "opened" でなければ
promise を "InvalidStateError" DOMException で reject
し返す。
[[readable]] に呼び出した結果か、
a promise
resolved with
undefined(もし this.[[readable]] が null の場合)。
[[writable]] に呼び出した結果か、
a promise
resolved with
undefined(もし this.[[writable]] が null の場合)。
[[readable]] および
this.[[writable]] がともに null であれば、
resolve
pendingClosePromise を undefined で完了。
[[pendingClosePromise]] に
pendingClosePromise をセット。
[[state]] を "closing" に。
[[state]]
を "closed" に
[[readFatal]] と
this.[[writeFatal]] を
false に。
[[pendingClosePromise]]
を null に。
undefined で解決。
[[pendingClosePromise]]
を null に。
forget() メソッドの手順は以下の通りです:
undefined を返す。
[[state]] を "forgetting" にする。
requestPort()の結果としてサイトに許可したシリアルポート一覧から
this を削除する。
[[state]] を "forgotten" にする。
undefined で実施。
この仕様は https://github.com/WICG/serial リポジトリ内のブロックリストファイルに依存しており、ウェブサイトがアクセスできるポートの集合を制限します。
URL url の BluetoothサービスクラスIDブロックリストのパース の結果は、カスタムサービスIDを表す リスト 型の UUID 値です。
シリアルポートプロファイル サービスクラスID は
値 "00001101-0000-1000-8000-00805f9b34fb" を持った
BluetoothServiceUUID
です。
{{BluetoothServiceUUID} の serviceUuid が
ブロックされたBluetoothサービスクラスUUID であるとは、以下の手順で true を返す場合です:
BluetoothUUID.getService()
に serviceUuid を渡して呼び出した結果とします。
true を返します。
false を返す。
-0000-1000-8000-00805f9b34fb" であれば
true を返す。
false を返します。
この仕様は、serial 属性で
Navigator
オブジェクトに公開されたメソッドを利用できるか制御する機能を定義します。
この機能のフィーチャ名は "serial" です。
この機能の デフォルト許可リスト
は 'self' です。
このセクションは規範的ではありません。
このAPIは [WEB-BLUETOOTH] および [WEBUSB] と類似のセキュリティリスクがあり、それらの教訓がここにも適用されます。主な脅威は次の通りです:requestPort()
パターンであり、これはユーザー操作を要し、かつ一度にひとつのデバイスだけのアクセス許可しか付与できません。このためサイトは接続デバイスを列挙して脆弱性を調べることができず、ユーザーが明示的に許可する必要があります。実装は、現在通信中であることやいつでも権限を取り消せるUIを視覚的に示すこともできます。
この仕様はネットワークベースの攻撃者によるコード注入を防ぐため、セキュアコンテキストから配信されることを要求します。これは、ユーザーがアクセス許可を判断する際、正しいサイトのアイデンティティを見せるためです。また、クロスオリジンのiframeで利用を許可するにはトップレベルドキュメントによる [PERMISSIONS-POLICY] でのopt-inも必要です。[CSP3]と組み合わせることで、これらの仕組みが悪意のあるコード注入攻撃の対策となります。
残る懸念は、ユーザーが悪意あるサイトに騙されてデバイスのアクセスを許可してしまうフィッシング攻撃です。これにより、デバイス本来の機能を用いた攻撃や、デバイスに悪意のあるファームウェアを仕込んでホストコンピュータ自体を攻撃することができます。ホストソフトは接続デバイスからの入力バリデーションが不十分である場合、攻撃されやすくなります。この分野のセキュリティ研究により、多くのソフトウェアベンダは接続デバイスを信頼すべきでないことを認識するようになっています。
この種の攻撃を完全に防ぐ仕組みはありません。ページからデバイスに送信されるデータは「不透明なバイト列」に過ぎないためです。特定のデータタイプを送信不可とする努力は、たいていメーカーが意図的にそれを送らせるための回避策を講じるなどして無効化されます。
ユーザーエージェントは更に機器へのアクセス制御手段を提供できます:
requestPort() を呼び出せるようにする設定。
システム管理者は、この設定をエンタープライズのポリシー管理で全社的に適用できます。このコントロールにより管理者は、特定のサイトに特定デバイスのみアクセス権限を自動付与し、それ以外を禁止することができます。
また、USBやBluetoothはプロトコル上メタデータを取得できるため、脆弱なデバイスリストの維持運用が現実的ですが、DB-25/DE-9/RJ-45等「純粋」なシリアルポートやUSB/Bluetooth-シリアル変換器といった一般的なものには識別可能なメタデータがありません。このため、こうしたデバイスを個別にブロックすることは不可能です。
このセクションは規範的ではありません。
シリアルポートおよびシリアルデバイスには2種類の機微な情報が含まれます。USB/Bluetoothデバイスの場合はベンダー/プロダクトID(=メーカー・型番)やシリアルナンバーやMACアドレスなどの識別情報、またシリアルコマンドで得られる機器固有ID等があります。加えて、機器自体が独自の個人情報を格納している場合もあります。デバイス許可管理を行うため、実装はUSBベンダーID・プロダクトID・シリアル番号といった情報をユーザー設定ファイルに保存して、許可済みデバイスを一意に識別するために利用することになります。これら情報はサイトと直接共有されることはなく、許可解除やサイトデータ削除時にクリアされます。
ページがデバイスアクセス権を得た後であれば、ページは機器が保持している他の個人情報を含む多数の情報にアクセスできる可能性があります。7. セキュリティに関する考慮事項 で説明した通り、ページからこうした情報へのアクセスを完全に阻止することは現実的でも望ましくもありません。
実装は利用者がアクセス許可デバイスを完全にコントロールできること、かつ明示的なユーザー操作なしでデバイス権限が与えられないことを保証すべきです。これは requestPort()
メソッドの意図です。これによりサイトは接続中全デバイスの列挙や情報収集ができず、ファイル選択UIと同様にユーザーが選択したポートやデバイス・ディレクトリだけをサイトが知ることになります。サイト利用中にユーザーに権限利用中である旨を通知(タブやアドレスバーのアイコン表示等)しても良いでしょう。
「プライベート」または「シークレット」ブラウジングモードのある実装は、通常のプロファイルで設定したデバイス権限が当該セッションに持ち越されず、そのセッション中に付与された権限も終了時には保存されないことを保証すべきです。こうしたセッションでデバイス権限を付与する際は、手動で個人情報を入力する場合と同様、デバイス識別子や個性情報を経由してセッション間ID特定につながる可能性があることを警告しても良いでしょう。
このAPIで許可を与えることが従来のWebセキュリティモデルの分離境界を破る側面を持つ場合があるため、利用者がAPIの力量を十分理解していない場合は驚くことがあります。セキュリティUIやドキュメントでは「サイトにデバイス権限を与える=そのデバイスや中身全てに完全アクセスできる」ことを必ず明示すべきです。
規範的でない旨が明記されている節以外にも、この仕様で記載されたオーサリングガイド・図・例・注記はすべて規範的なものではありません。それ以外のすべては規範的です。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: