1. はじめに
-
このセクションは規範的ではありません。*
手書き入力は描画です。描画は人間のペン先の動きをデジタルで再現するために必要な情報を記録します。
ここで提案するAPIは、オペレーティングシステムの機能をWebに公開することを目的としています。手書き認識の機能はOSによって異なることがあるため、このAPIはOS固有の機能と容易に統合できる柔軟な設計を目指します。
ユーザーエージェントはWeb APIのデータ構造(本仕様で定義)を、ホストOSで利用可能なものに変換し、Web APIとOSのAPIを接続することが期待されます。
このAPIは、どのプラットフォームでも同じ動作をする認識を定義しようとはしていません。
1.1. 定義
本仕様では以下の概念を定義します。例として手書きの “WEB” を用います:-
描画は複数のストロークで構成されます(例:上記のEは3つのストロークから成ります)。
-
ストロークは、ある一定期間内の一続きのペン先の動きを表します(例:
touchstartから対応するtouchendイベントまで)。動きの軌跡は一連のポイントで表されます。 -
ポイントは、空間と時間でのペン先の観測点です。これはペン先のタイムスタンプおよび書き込み面上の位置(例:
touchmoveイベント)を記録します。 -
転写 は、描画で書かれた文字を表すUnicode文字列です(例:"WEB")。
手書き認識器は(通常は外部アプリやサービスで実装される)インターフェイスで、以下を行います:
どのようなものを手書き認識器とみなすかはユーザーエージェントの裁量に委ねられます。
データ変換を通じて手書き認識器に適合する形式に変換するため、ユーザーエージェントは本仕様で定義されたものと手書き認識器で使われる同等の概念をマッチさせるべきです。
手書き認識器は、Webアプリケーションが手書きをよりよく処理するための追加情報(例:手書きから1文字削除するなど)を出力する場合があります。
セグメンテーションは、書記素(ユーザーが知覚する1文字)をそれを構成するストロークやポイントにマッピングします。書記素は複数のUnicodeコードポイントにまたがる場合があります。
\u0078g̈は2つのUTF-16コードポイントで構成されています:
\u0067\u0308。षिも2つのUTF-16コードポイントで構成されています:
\u0937\u093f。
手書きテキスト "int" を例にします:
-
ストローク1と5が文字 "i" を構成
-
ストローク2が文字 "n" を構成
-
ストローク3と4が文字 "t" を構成
2. APIイディオム
本仕様で言及されているタスクソースは、手書き認識タスクソースです。
アルゴリズムが手書き認識APIタスク Tをキューに投入するとき、ユーザーエージェントは、グローバルタスクをキューに積み、手書き認識タスクソース、およびグローバルオブジェクト、現在のレルムレコードを利用します。
特に指定のない限り、アルゴリズム手順で生成されたJavaScriptオブジェクトのレルムは現在のレルムレコードとします。
3. 機能クエリ
機能クエリインターフェースは、Webアプリケーションが実装依存の機能を問い合わせて利用可否の判断ができるようにします。
const modelConstraint= { languages: [ 'zh-CN' , 'en' ] }; const modelDesc= await navigator. queryHandwritingRecognizer( modelConstraint); // \`modelDesc\` describes the handwriting recognizer meeting the \`modelConstraint\`. // If the constraints can't be satisfied, \`modelDesc\` will be null. { textAlternatives: true , textSegmentation: true , hints: { alternatives: true , textContext: true , inputTypes: [ 'mouse' , 'touch' , 'stylus' ] } }
[SecureContext ]partial interface Navigator {Promise <HandwritingRecognizerQueryResult ?>(queryHandwritingRecognizer HandwritingModelConstraint ); };constraint dictionary {HandwritingModelConstraint required sequence <DOMString >; };languages dictionary {HandwritingRecognizerQueryResult boolean ;textAlternatives boolean ;textSegmentation HandwritingHintsQueryResult ; };hints dictionary {HandwritingHintsQueryResult sequence <HandwritingRecognitionType >;recognitionType sequence <HandwritingInputType >;inputType boolean ;textContext boolean ; };alternatives enum {HandwritingRecognitionType ,"text" };"per-character" enum {HandwritingInputType ,"mouse" ,"stylus" };"touch"
3.1.
queryHandwritingRecognizer(constraint)
このメソッドはWebアプリケーションが基盤となる認識器の機能を問い合わせ、利用するかどうか判断する方法を提供します:
-
制約が満たされる場合は、手書き認識器の記述が返されます
-
制約が満たされない場合は、
nullが返されます
同じHandwritingModelConstraint
を使って、createHandwritingRecognizer(constraint)
を呼び出し、制約を満たすHandwritingRecognizer
を作成できます。
queryHandwritingRecognizer(constraint)
メソッドが呼び出されたとき、以下を行います:
-
もし constraint に
languagesメンバーがなければ、指定した値で拒否された Promise として新しいTypeErrorを返す。 -
p を 新しい Promise とする。
-
次の手順を 並列に 実行する:
-
次のいずれかが真である場合:
-
ユーザーエージェントが、変換された constraint を満たすプラットフォーム依存の 手書き認識器 を見つけるか作成できない。
手書き認識 API タスクをキューに入れて p を
nullで解決し、残りの手順を中止する。 -
それ以外の場合、手書き認識 API タスクをキューに入れて 次を行う:
-
result を新しい
HandwritingRecognizerQueryResultとする -
手書き認識器の機能記述を変換し、result の全てのメンバーを埋める。
-
p を解決する に際して result を渡す。
-
-
p を返す。
実装はHandwritingRecognizerQueryResult
およびHandwritingHintsQueryResultへの変換で次のルールに従うべきです:
-
認識器がヒントを一切受け付けない場合、
hintsをnullとします。 -
サポートされていない機能やヒントは、その属性を
nullにします。 -
enumヒントがサポートされている場合、その属性に利用可能な値のリストをセットします。
-
enum以外のヒントがサポートされている場合、その属性を
trueにします。
3.2.
HandwritingModelConstraint
属性
これは、基盤となる手書き認識器が(作成される場合)満たすべき制約を説明します。
また、createHandwritingRecognizer(constraint)で
手書き認識器を作成する際にも使用されます。
languages- 認識器が認識すべき言語を示す[BCP47]言語タグのリストです。
複数の言語が指定された場合、認識器は全ての言語を認識できる必要があります。
ユーザーエージェントは、与えられた言語タグのすべての可能なスクリプトを考慮するべきです。例えば、「az-Latn」(ラテン文字のみ対応)だけの認識器は、「az」タグ(アゼルバイジャン語)には使うべきではありません。アゼルバイジャン語はキリル文字("az-Cyrl")でも書かれます。
スクリプトの区別が重要な場合は、最も具体的な言語タグを使うことを検討してください。例:アゼルバイジャン語のラテン表記専用アプリでは"az-Latn"を指定。
一部の認識器は単一言語のみ対応です。より良い相互運用性のために言語ごとに認識器を作成することを推奨します。
3.3. HandwritingRecognizerQueryResult
属性
これは手書き認識器実装の固有機能を記述します。
textAlternatives- 実装が1つではなく複数の候補転写を返す場合はtrueとなります。
textSegmentation- 実装が各転写のセグメンテーション情報を返すならtrueです。
hintsHandwritingHintsQueryResultオブジェクト。startDrawing()で受け付け可能なヒントを記述します。
3.3.1. HandwritingHintsQueryResult
属性
これは、startDrawing()
に任意で渡せるヒント群を記述し、精度や性能アップに役立ちます。
慣例的に、ここの属性名はstartDrawing()
メソッドで受け付けるものと一致します。
recognitionTypeHandwritingRecognitionType列挙型のリストで、どのようなテキストが描かれる可能性が高いかを表します。"text"- 普通の文章など、本当の単語を書く自由形式のテキスト。例:日常会話の文。
"per-character"- 手書きが独立した書記素(ユーザーが知覚する1文字)で連なる形式。例:シリアル番号やライセンスキー。
inputTypeHandwritingInputType列挙型のリストで、どう描かれたかを表します。"touch"- 指で描かれたもの
"stylus"- スタイラスで描かれたもの
"mouse"- マウスカーソルで描かれたもの
textContext- textContextが受け付けられるかの真偽値。
textContextは、ユーザーに見せているテキストや、今回の描画より前の認識済みテキスト文字列を含みます。 alternatives- 返す転写候補数の最大値を設定可能ならtrueになります。
getPredictionで返される候補数の上限となります。
ヒントを指定しても結果の転写内容がそれに対応することは保証されません。
4. 手書き認識器の作成
HandwritingRecognizer
は認識を行うために必要なリソースを管理します。
const modelConstraint= { languages: [ 'en' ] }; try { const recognizer= await navigator. createHandwritingRecognizer( modelConstraint); // Use \`recognizer\` to perform recognitions. } catch ( err) { // The provided model constraint can't be satisfied. }
[SecureContext ]partial interface Navigator {Promise <HandwritingRecognizer >(createHandwritingRecognizer HandwritingModelConstraint ); };constraint
4.1.
createHandwritingRecognizer(constraint)
メソッド
このメソッドは、与えられたHandwritingModelConstraint
を満たし、認識を行うために必要なリソースを予約するHandwritingRecognizer
オブジェクトを生成します。これは手書き認識器へのエントリーポイントです。
-
制約が満たされ、かつOS上に十分なリソースがあれば
HandwritingRecognizerオブジェクトとして解決されます。 -
そうでなければ、エラーで拒否されます。
ユーザーエージェントは、ユーザーに手書きモデルのインストールやダウンロードを促す場合があります。Webアプリケーションは、このメソッドが常に即座に解決するとは限らないと想定してください。
createHandwritingRecognizer(constraint)
メソッドが呼び出されたときは、次のようにします:
-
constraintに
languagesメンバーがなければ、TypeErrorでpromiseをリジェクトします。 -
pを新しいpromiseとします。
-
次のステップを並列で実行します:
-
手書き認識APIタスクをキューイングして:
-
ユーザーエージェントが認識用
手書き認識器を作成できない場合、各失敗理由に応じて新しい例外でpをrejectします:-
constraintの
languagesが空のリストなら"NotSupportedError"DOMException。 -
変換後のconstraintを満たす
手書き認識器が見つからない場合も"NotSupportedError"DOMException。 -
新しく認識器を作ることでアクティブな認識器の合計数の上限を超える場合は
QuotaExceededError。 -
Webアプリが再試行可能な場合は
"OperationError"DOMException。 -
それ以外の失敗は
"UnknownError"DOMException。
-
-
それ以外の場合:
-
resultを新しい
HandwritingRecognizerオブジェクトとします。 -
resultに前のステップで生成したプラットフォーム依存の
手書き認識器を結び付けます。 -
resultのactiveフラグを
trueにします。 -
解決する p を result で。
-
-
-
pを返します
5. 認識器の使用
const drawingHints= { textContext: "Hello world." } const drawing= recognizer. startDrawing( textContext) // \`drawing\` で何か処理を行う。 // 認識器に関連付けられたリソースを解放する。 recognizer. finish()
5.1.
HandwritingRecognizer
オブジェクト
[Exposed =Window ,SecureContext ]interface {HandwritingRecognizer HandwritingDrawing (startDrawing optional HandwritingHints = {});hints undefined (); };finish dictionary {HandwritingHints DOMString = "text";recognitionType DOMString = "mouse";inputType DOMString ;textContext unsigned long = 3; };alternatives
HandwritingRecognizer
にはactiveフラグ(boolean)があり、初期値はtrue、finish()
メソッドが呼ばれるとfalseになります。
認識器のactiveフラグがtrueの間、Webアプリはこの認識器に新しい描画を関連付けて
認識処理を実行できます。
ユーザーエージェントは、ひとつのサイトで保持できるactiveな手書き認識器の総数を制限する場合があります。
5.2.
startDrawing(hints)
このメソッドは、以降の認識のための描画情報を保存するHandwritingDrawing
を作成します。
HandwritingDrawing
はstrokes(リスト。初期値は空)と、それを構成するHandwritingStroke群を持ちます。
HandwritingDrawing
はrecognizerというフィールドで、このHandwritingDrawing
を作成したHandwritingRecognizer
を参照します。
startDrawing(hints)
が呼ばれたときは、次のようにします:
-
もし
this.active フラグがtrueでない場合、新しいDOMExceptionオブジェクトをスローし、そのnameメンバーを"InvalidStateError"にして中止する。 -
提供された hints を適した形式に変換する を 手書き認識器 に対して。
-
新しい
HandwritingDrawingを result として作成し、必要であれば変換したヒントをそこに格納する。 -
Set result.recognizer を
thisに設定する。 -
result を返す。
渡されたhintsに対応しないフィーチャが含まれている場合、ユーザーエージェントは該当属性を無視するべきです。
ヒントが省略された場合、ユーザーエージェントは任意のデフォルト値を適用してよいです。
ユーザーエージェントは、変換したhintsを手書き認識器の描画オブジェクトに直接渡すことも考えられます(HandwritingDrawing内に保存しなくてもよい)。
5.3.
finish()
このメソッドはthisのactiveフラグをfalseにし、割り当てられた手書き認識器リソースを解放し、
thisの今後の操作を失敗させます。
ユーザーエージェントは、手書き認識器に関連付いたリソースを解放すべきです。
finish()呼び出し以降、getPrediction()
を本認識器作成のHandwritingDrawing
で呼び出しても失敗します。
6. HandwritingDrawingの構築
HandwritingDrawing
は描画に関するコンテキスト情報保持と、構成するストローク・ポイント群の管理を行います。これは描画そのものを表します。
ユーザーエージェントは、全ストロークとポイントをメモリ上に一旦保持し、getPrediction()
呼び出し時に手書き認識器向け形式に変換して利用してもよいです。この場合、HandwritingDrawing
およびHandwritingStroke
はリストの役割を果たします。
HandwritingStroke
や
HandwritingDrawing
のメソッド呼び出しタイミングでそれらを手書き認識器に渡す方法でもかまいません。
この場合、HandwritingDrawing
や HandwritingStroke
はプラットフォーム依存オブジェクトのラッパー的存在となります。
ユーザーエージェントは、関連メソッド呼び出し時にストロークへ“修正あり”マークを付けて変更追跡(change tracking)を行うことで、getPrediction()
のパフォーマンス向上を図ることができます。これにより、対応する手書き認識器でインクリメンタルな認識処理も可能となります。
例:3段落からなる描画があり、前回getPrediction()
の予測が保存されています。この後3段落目にストローク追加があると、変更追跡あり実装ならその段落(や付近のストローク)に対し新たな認識リクエストと、既存結果と統合した返却が可能です。
const handwritingStroke= new HandwritingStroke() // ストロークへポイントを追加 handwritingStroke. addPoint({ x: 1 , y: 2 , t: 0 }); handwritingStroke. addPoint({ x: 7 , y: 6 , t: 33 }); // このストロークの全てのポイントを取得 // 返却はコピー。返却値を変更してもストローク本体に影響しない。 const points= handwritingStroke. getPoints(); [ { x: 1 : , t: 2 , t: 0 }, { x: 7 , y: 6 , t: 33 } ]; // ストローク中の全ポイント消去 handwritingStroke. clear(); // 描画にストロークを追加 drawing. addStroke( handwritingStroke); // 描画内ストロークすべてを取得 // 返却は HandwritingStroke のリスト。Webアプリで // たとえば HandwritingStroke.addPoint() などによるストローク修正も可能。 drawing. getStrokes(); [ HandwritingStroke, /* ... */ ] // 描画から特定ストローク削除 drawing. removeStroke( handwritingStroke); // 描画から全ストローク削除 drawing. clear();
[Exposed =Window ,SecureContext ]interface {HandwritingDrawing undefined (addStroke HandwritingStroke );stroke undefined (removeStroke HandwritingStroke );stroke undefined ();clear sequence <HandwritingStroke >();getStrokes Promise <sequence <HandwritingPrediction >>(); }; [getPrediction SecureContext ,Exposed =Window ]interface {HandwritingStroke ();constructor undefined (addPoint HandwritingPoint );point sequence <HandwritingPoint >();getPoints undefined (); };clear dictionary {HandwritingPoint required double ;x required double ; // 任意。描画の基準時点からの経過ミリ秒数。y DOMHighResTimeStamp ; };t
t を HandwritingPoint
で渡す場合は、
HandwritingDrawing
毎に全 t の起点を揃えてください。
例:startDrawing()
呼び出し時点を t === 0 としたり、各ポイント取得時に Date.now()(例:touchmove
イベント発生時)を使ってもよいです。
6.1. HandwritingStroke
HandwritingStroke
はストロークを表します。1つの動きを再現するのに必要な情報を保持します。
HandwritingStroke
はPointsを持ち、これはこのストロークのリストでポイントを格納します。points
は初期状態では空です。
6.1.1.
HandwritingStroke()
-
新しい
HandwritingStrokeオブジェクトを作成し、resultとする。 -
resultを返す。
6.1.2.
addPoint(point)
thisにポイントを追加します。呼び出された際、以下を実行します:
-
pointに
xメンバーがなければ、TypeErrorをスローし中止。 -
point.
xが数値でなければ、TypeErrorをスローし中止。 -
pointに
yメンバーがなければ、TypeErrorをスローし中止。 -
point.
yが数値でなければ、TypeErrorをスローし中止。 -
pointに
tメンバーがあり、それが数値でなければ、TypeErrorをスローし中止。 -
pという新しいオブジェクトを作成する。
-
p.
xにpoint.xを設定する。 -
p.
yにpoint.yを設定する。 -
pointに
tがあれば、p.tにpoint.tを設定する。
pointにtがない場合、デフォルト値・補間数値等は利用せず、p.tが未設定であることを保持します。
addPoint(point)
呼び出し後にpointを変更しても、その後のHandwritingStrokeに影響しません。
6.1.3.
getPoints()
このメソッドは、このストローク内のポイントを返します。
ディープコピーにより内部の points への変更を防ぎ、変更追跡を可能にします。
getPoints()
の返り値を変更してもストロークには影響しません。
6.1.4. clear()
このメソッドは、このストロークのすべてのポイントを削除し、このストロークを空にします。
6.2.
HandwritingDrawing
6.2.1.
addStroke(stroke)
-
stroke が
HandwritingStrokeのインスタンスでない場合、TypeErrorをスローし中断。
6.2.2.
removeStroke(stroke)
-
stroke が
HandwritingStrokeのインスタンスでない場合、TypeErrorをスローし中断。
6.2.3.
getStrokes()
このメソッドは、この描画内のストローク一覧を返します。
6.2.4.
clear()
7. HandwritingDrawingの予測を取得
// この描画内のストロークに対する予測を取得 const predictions= await drawing. getPrediction(); // \`predictions\`は\`HandwritingPrediction\`のリストで、属性は // 認識器の機能やqueryHandwritingRecognizer()のモデル記述に依存。 // // 例えばrecognizerがtextSegmentationをサポートする場合: [ { text: "hello" , segmentationResult: [ { grapheme: "h" , beginIndex: "0" , endIndex: "1" , drawingSegments: [ { strokeIndex: 1 , beginPointIndex: 0 , endPointIndex: 32 }, { strokeIndex: 2 , beginPointIndex: 0 , endPointIndex:: 40 }, ] }, { grapheme: "2" , beginIndex: "1" , endIndex: "2" , drawingSegments: [ { strokeIndex: 2 , beginPointIndex: 41 , endPointIndex:: 130 }, ] }, // ... ] }, { text: "he11o" , segmentationResult: [ /* ... */ ] }, // startDrawing()で指定したalternatives個まで ];
7.1.
getPrediction()
getPrediction()
メソッドは this 描画の予測リストとそのメタデータを返します。
予測は信頼度の高い順で並び、空でなければ最初の予測が最もありそうな結果です。
手書き認識器が何も認識できなかった場合、getPrediction()
は空の リスト
で解決されるべきです。
ユーザーエージェントは 変更追跡 を用いてインクリメンタル認識を行い、パフォーマンスを向上させる場合があります。
getPrediction()
が呼ばれたとき:
-
this.recognizer.active がtrueでなければ "InvalidStateError" DOMException でrejectされたpromise を返す。 -
this.strokes が空なら新しい空のリストで解決されるpromise を返す。 -
p を新しいPromiseとし、次のステップを 並列で実行:
-
変換した描画を手書き認識器に渡す。
-
手書き認識器が予測を返すのを待つ。
-
手書き認識APIタスクとして以下を実行:
-
result をリストとして用意。
-
-
pred を変換する
HandwritingPredictionidl_pred. -
idl_pred を result に追加。
-
-
p を result で解決。
-
-
-
p を返す
7.2. HandwritingPrediction
属性
HandwritingPrediction
は手書き認識器からの予測結果を表します。
dictionary {HandwritingPrediction required DOMString ;text sequence <HandwritingSegment >; };segmentationResult dictionary {HandwritingSegment required DOMString ;grapheme required unsigned long ;beginIndex required unsigned long ;endIndex required sequence <HandwritingDrawingSegment >; };drawingSegments dictionary {HandwritingDrawingSegment required unsigned long ;strokeIndex required unsigned long ;beginPointIndex required unsigned long ; };endPointIndex
text- 描画の転写を表す
DOMString。 segmentationResult-
各認識済みのグラフェム(ユーザーが知覚する文字)と、その構成ストロークとポイントの対応を示す
HandwritingSegmentのリスト。手書き認識器がテキストのセグメンテーション をサポートしない場合は
nullとなります。Webアプリケーションは
textSegmentationでこの属性がnullになりうるか判別できます。
7.2.1. HandwritingSegment
属性
HandwritingSegment
は描画からセグメント化された1つのグラフェムについて記述します。
grapheme- グラフェムを表す
DOMString。 beginIndextext内でこのグラフェムが始まるインデックス。endIndex-
text内でこのグラフェムが終わる(次のグラフェムが始まる)インデックス。 drawingSegments-
このグラフェムを構成する描画部分を記述する
HandwritingDrawingSegmentのリスト。
text
を beginIndex
と endIndex
でスライスすると、grapheme
になります。
// Webアプリケーションは `beginIndex` と `endIndex` で `text` をスライスできます。 // 例: "घोषित" の `HandwritingPrediction` const prediction= { // UTF-16コードポイント: \u0918 \u094b \u0937 \u093f \u0924 // グラフェム: घो, षि, त text: "घोषित" , segmentationResult: [ { grapheme: "घो" , beginIndex: "0" , endIndex: "2" }, { grapheme: "षि" , beginIndex: "2" , endIndex: "4" }, { grapheme: "त" , beginIndex: "4" , endIndex: "5" }, ] } // 次のようになる: prediction. text. slice( 0 , 1 ) === "घो" ; prediction. text. slice( 2 , 4 ) === "षि" ; prediction. text. slice( 4 , 5 ) === "त" ; // 2番目のグラフェム (षि) はspliceで削除できる const withoutSecondGrapheme= ( [... prediction. text] . splice( prediction. segmentationResult[ 1 ]. beginIndex, prediction. segmentationResult[ 1 ]. endIndex) . join( '' ) ); // => "घोत"
7.2.2.
HandwritingDrawingSegment
属性
HandwritingDrawingSegment
は HandwritingStroke
の連続領域を表します。
各属性は HandwritingStroke
が HandwritingDrawing
で getPrediction()
された時点に基づきます。
strokeIndexHandwritingDrawing.strokes 内のHandwritingStrokeのインデックス。beginIndex- 描画セグメントの開始インデックス。
endIndex- 描画セグメントの終了インデックス(次の描画セグメントの開始点)。
8. プライバシーに関する考慮事項
このセクションは規範的ではありません。フィンガープリントベクターは、フィーチャー検出と認識器の実装という2つの部分から発生します。
公開される情報量(エントロピー)はユーザーエージェントの実装に依存します。一律の解決策はないと考えるため、必要に応じてプライバシー保護(例:許可プロンプト)を適用するかはユーザーエージェントの判断を推奨します。
フィーチャー検出 で以下の情報が漏れる可能性があります:
-
ユーザーが選択した言語(またはインストール済みの手書き認識モデル)。これは
navigator.languagesでも取得可能。 -
利用されている認識器の実装(サポートされている機能のまとめから判断)。これによりOSやそのバージョンをある程度推測可能な場合があります。
フィンガープリント対策としては以下が考えられます:
-
プライバシーバジェット:Webサイトが過剰に問い合わせた場合、ユーザーエージェントはPromiseを拒否する。
-
許可プロンプト:ユーザーエージェントが無制限の手書き認識機能の利用をユーザーに確認する。
-
ハードコーディング:ビルド時に言語や機能を特定できる場合、ユーザーエージェントが固定値を返す。
認識器の実装 もOS、デバイスやユーザーの習慣に関する情報を露呈する可能性があります。これは使用される認識器技術に大きく依存します。
下記は実装の種類とそのリスクです:
-
認識器非対応:フィンガープリントリスクなし。
-
クラウドベース認識器:ほぼリスクなし。Webサイトがクラウドサービス判定(推論結果をAPI直叩きした結果と比較)できる可能性はあるが、追加のユーザー・デバイス情報は公開されない。
-
ステートレスモデル(最も一般的):出力は入力描画とモデル自身のみに依存。
-
ブラウザ内のみで更新可能なモデル:Webサイトはブラウザのバージョン(他手段でも判定可能)を知ることができる。
-
ブラウザ外でも更新されうるモデル(OS APIを呼び出す等)の場合、状況によりWebサイトは以下を取得し得る:
-
モデルが毎回OSアップデート時に更新されていればOSのバージョン。
-
一部のOSアップデートのみで更新される場合はバージョン範囲。
-
モデルが個別/オンデマンドで更新される場合は特定のパッチバージョン等。
-
-
ハードウェアアクセラレータ(例:GPU)を利用するモデルの場合、特定ハードウェアに関する情報が出力により漏れることもある。
-
-
ステートフル/オンライン学習型モデル(最悪想定):これらのモデルは過去の使用に基づき学習しうる。例:ユーザーのIME習慣によって出力を調整するOS認識器。これらはユーザーに関する大量の情報をさらし大きなリスクとなる。
ただしこのタイプの実装があることは現在把握していません。この種のモデルを使用する場合は必ずプライバシー対策や、セッション毎クリアな状態の使用を推奨します。
フィンガープリントのコスト:モデル差異を活用するため、フィンガープリント手法は手書き(敵対例)サンプル一式を作成・管理するコストを要します。負担は大きい可能性がありますが、本気で取り組めばサンプルを取得できると考えてよいでしょう。