1. はじめに
この節は非規範的です。
自動入力は、日々何百万人ものユーザーの手間を軽減する、Webの重要な機能です。 ログイン画面、電子商取引、連絡先フォームなどで広く使用されています。 特に商取引および購入手続きのフローでは、自動入力は購入者の体験と販売者の成果の両方に 大きな利点をもたらします。
同時に、Webの自動入力には、部分的または不完全な入力、 ブラウザー間の相互運用性の問題、開発者にとって実装および保守のコストが高いことなど、いくつかの欠点があります。
重要な例の1つは住所の自動入力です。これは正しく実装された場合、動的なフォームになります。 地域によって、住所入力の形式や要件は異なります。国を選択するには、 フォームを変更(フィールドの並べ替え、追加、削除)する必要があり、ユーザーからの入力に 依存しますが、自動入力がこの対話を仲介するため、レンダリングされたフォームに 正しく応答しない場合があります。
現在の「業界標準」の解決策では、適切な情報を予測して 取得し、それをユーザーに提示しようとする非表示のフォームフィールドを使用する必要があります。この解決策は壊れやすく、 複雑です。さらに悪いことに、正当なユースケースを実現するための非表示フィールドの使用を定着させますが、同じ 手法は悪意ある者によって悪用される可能性があり、実際に悪用されています。
この仕様は、自動入力値が
フォームフィールドに確定される前に発火するAutofillEvent
を導入し、開発者が次のことを行えるようにします。
-
自動入力されようとしている値を調査する
-
それらの値に基づいてフォームを動的に適応させる(たとえば、国固有の住所フィールドを表示する)
-
フォームが自動入力値を受け入れる準備ができた時点をユーザーエージェントに通知する
1.1. 目標
-
ユーザー: 自動入力の信頼性を高め、将来的に 非表示フィールドへの入力を廃止できる可能性への道を開く
-
サイト開発者: 非表示 フィールドを使用して住所の自動入力に対処するために必要な複雑さを軽減し、実装固有の回避策の必要性を減らす。
-
自動入力プロバイダー: 新しいAPIとシームレスに連携するフックを サードパーティの自動入力プロバイダーに提供する
1.2. 例
< form id = "checkout" > < input autocomplete = "name" placeholder = "氏名" > < input autocomplete = "street-address" placeholder = "番地" > < input autocomplete = "address-level2" placeholder = "市区町村" > < input autocomplete = "postal-code" placeholder = "郵便番号" > < input autocomplete = "country" placeholder = "国" > <!-- 州/都道府県フィールドは、必要とする国に対して動的に追加される --> </ form > < script > document. addEventListener( 'autofill' , async function ( event) { // 自動入力値から国の値を見つける let countryValue= null ; let formElement= null ; // 国の要素と値を見つける for ( const [ element, value] of event. autofillValues) { if ( element. autocomplete=== 'country' ) { countryValue= value; formElement= element. form; break ; } } // 米国の住所を入力する場合、州の選択欄を追加する必要がある if ( event. refill!== null ) { if ( countryValue=== 'US' ) { // 州フィールドがすでに存在するか確認する const existingState= formElement. querySelector( '[autocomplete="address-level1"]' ); if ( ! existingState) { // 米国の住所用の州選択欄を作成して挿入する const stateSelect= document. createElement( 'select' ); stateSelect. autocomplete= 'address-level1' ; stateSelect. name= 'state' ; stateSelect. innerHTML= ` <option value="">州を選択...</option> <option value="AL">アラバマ州</option> <option value="AK">アラスカ州</option> <option value="AZ">アリゾナ州</option> <option value="CA">カリフォルニア州</option> <option value="CO">コロラド州</option> <!-- ... その他の州 ... --> <option value="WY">ワイオミング州</option> ` ; // 郵便番号フィールドの前に挿入する const postalCode= formElement. querySelector( '[autocomplete="postal-code"]' ); postalCode. parentNode. insertBefore( stateSelect, postalCode); // フォームが変更され、自動入力を再実行すべきことを通知する await event. refill(); } } else if ( countryValue=== 'UK' ) { ... 英国固有のロジックを追加する} } else { // UAは再入力をサポートしていない。非表示フィールドから値を抽出するか、 // 値を手動で入力する必要があることをユーザーに通知する。 } }); </ script >
autofillValues
属性は、自動入力値エントリーのリストを返します。各
エントリーは、対象のHTMLElement
と入力される値のタプルです。開発者は
これらのエントリーを反復処理して、保留中の自動入力データを調査し、フォームを
適応させる必要があるかどうかを判断できます。
フォーム構造が変更された後(たとえば、国固有のフィールドを追加するために、場合によっては非同期で)、
開発者はrefillを呼び出します。
これにより、フォームが
変更され、更新されたフォーム構造を使用して自動入力操作を再試行すべきことがユーザーエージェントに通知されます。
注: refill
属性は、イベントの2回目の配送時
(フォームの変更後)にはnullとなり、無限ループを防止します。
2. 概念
2.1. 自動入力値エントリー
自動入力値 エントリーは、次の要素からなるタプルです。
-
HTMLElement— 自動入力値を受け取るフォームコントロール -
DOMString— 入力される、ユーザーの自動入力プロファイルから取得した値
ユーザーエージェントは、コントロールの
autocomplete
属性に基づいて、フォームコントロールを自動入力データと照合します([HTML]の自動入力フィールド名を参照)。
また、実装定義のヒューリスティックを使用することもあります。
2.2. 再入力操作
再入力操作により、 開発者は、自動入力値に応じてフォーム構造が 変更され、ユーザーエージェントがフォームへの入力を再度試みるべきことを通知できます。
3. AutofillEventインターフェイス
[Exposed =Window ]interface :AutofillEvent Event {(constructor DOMString ,type optional AutofillEventInit = {});eventInitDict readonly attribute FrozenArray <AutofillValueEntry >autofillValues ;readonly attribute RefillCallback ?refill ; };callback =RefillCallback Promise <undefined > ();dictionary :AutofillEventInit EventInit {sequence <AutofillValueEntry >= [];autofillValues boolean =allowRefill true ; };typedef sequence <any >; // AutofillValueEntryは[HTMLElement, DOMString]のタプルである // 最初の要素はフォームコントロールであり、2番目の要素は入力する値であるAutofillValueEntry
AutofillEvent
インターフェイスは、ユーザーエージェントがフォームフィールドを自動入力しようとするときに
配送されるイベントを表します。
3.1. 属性
autofillValues属性は、
自動入力値
エントリーのリストを返します。各エントリーは、最初の要素がHTMLElement
(入力対象となるフォームコントロール)であり、2番目の要素がDOMString
(入力する値)であるタプルです。
refill属性は、RefillCallback
または
nullを返します。nullでない場合、このコールバックを呼び出すとPromise
が返され、これを待機すると、
フォーム構造が変更され、自動入力を再試行すべきことがユーザーエージェントに通知されます。
refill
属性は、次の場合にnullとなります。
-
以前に
refillを呼び出した後の再試行としてイベントが配送された場合、 または -
ユーザーエージェントが、この自動入力操作には再入力が適切でないと判断した場合。
これにより、ページがフォームを継続的に変更して再入力を要求する無限ループを防止します。
各AutofillEvent
には、関連付けられた自動入力値リスト
(自動入力値
エントリーのリスト)があり、初期状態では空のリストです。
各AutofillEvent
には、関連付けられた再入力許可フラグ
(真偽値)があり、
初期値はtrueです。
各AutofillEvent
には、関連付けられた配送タイムスタンプ
(DOMHighResTimeStamp)があり、
初期値は0です。
各AutofillEvent
には、関連付けられた再入力保留フラグ
(真偽値)があり、
初期値はfalseです。
4. 処理モデル
4.1. 自動入力イベントの発火
-
AutofillEventを使用してイベントを作成した結果を、eventとします。 -
eventの
type属性を「autofill」に初期化します。 -
eventの
bubbles属性をtrueに初期化します。 -
eventの
cancelable属性をfalseに初期化します。 -
eventの自動入力値リストを entriesに設定します。
-
eventの再入力許可フラグを allowRefillに設定します。
-
documentに対してeventを配送します。
-
documentに対して、entriesを使用して自動入力操作を実行します。
注: 自動入力操作は、イベントが配送された直後に実行されます。
refill
コールバックにより、ページはフォーム構造を変更した後、
実装定義のタイムアウト期間内に追加の自動入力処理を要求できます。
4.2. 再入力要求の処理
AutofillEvent
eventを指定して再入力
要求を処理するには、次の手順を実行します。
-
現在の高分解能時刻をnowとします。
-
nowからeventの配送タイムスタンプを引いた値を、elapsedとします。
-
実装定義の期間をrefillTimeoutとします。
-
elapsedがrefillTimeoutより大きい場合は、「
InvalidStateError」DOMExceptionで拒否されたPromiseを返します。 -
eventの再入力許可フラグがfalseの場合は、「
InvalidStateError」DOMExceptionで拒否されたPromiseを返します。 -
eventの再入力保留フラグがtrueの場合は、「
InvalidStateError」DOMExceptionで拒否されたPromiseを返します。 -
eventの再入力保留フラグをtrueに設定します。
-
新しい Promiseをpromiseとします。
-
eventに関連する文書をdocumentとします。
-
promiseを返し、並行して次の手順を実行します。
-
更新された自動入力値 エントリー(変更されたフォームに対してユーザーの自動入力データを再照合したもの)をentriesとします。
-
次の処理を行うタスクをキューに追加します。
-
document、entries、およびfalseを指定して、自動入力イベントを発火します。
-
documentに対して、entriesを使用して自動入力操作を実行します。
-
promiseをundefinedで解決します。
-
-
注: タイムアウトは、応答性と、
ページがrefillを呼び出すための十分な時間を確保することとの
バランスを取るうえでユーザーエージェントに柔軟性を与えるため、実装定義です。
ユーザーエージェントは、
良好なユーザー体験を提供するタイムアウトを選択するべきです。
注: 再試行の配送時(refill
が呼び出された後)には、
refill
属性はnullとなり、無限ループを防止します。
4.3. HTML自動入力との統合
ユーザーエージェントの自動入力機構が起動され(たとえば、自動入力UIに対するユーザーの操作によって)、 ユーザーが入力する値を選択した場合、ユーザーエージェントは、それらの値をフォームフィールドに確定する前に、 自動入力イベントを発火しなければなりません。
5. 「full-address」オートコンプリートトークン
この仕様は、新しい自動入力フィールド名「full-address」を導入します。
フォームコントロールのautocomplete
属性が「full-address」に設定されている場合、
ユーザーエージェントは、現在のフォームに存在しない可能性がある
フィールドを含む、ユーザーの完全な住所データへのアクセス許可を要求するべきです。
これにより、フォームはAutofillEventを介して包括的な住所情報を受け取り、
ユーザーの住所に関連するすべてのフィールドを収容できるように、フォーム構造を
動的に適応させることができます。
full-addressの使用:
< form autocomplete = "full-address" > < input name = "country" autocomplete = "country" > < div id = "dynamic-address-fields" ></ div > </ form >
6. セキュリティおよびプライバシーに関する考慮事項
AutofillEvent
は、自動入力値がフォームフィールドに確定される前にJavaScriptへ公開します。
ユーザーエージェントは、自動入力に対するユーザーの明示的な同意が与えられた後
(たとえば、ドロップダウンから自動入力候補を選択することによって)にのみイベントが発火されることを保証するべきです。
APIの形状では、自動入力値のキーとして要素が必要になるため、イベントに渡されるデータは、 ユーザーエージェントがページ上のフォームに入力することを意図しているデータに限定されます。
refill()呼び出しの後にイベントが発火する場合、フォームには、
ユーザーエージェントが最初にフォームへ入力した時点では存在しなかった新しいフィールドが含まれる可能性が高いことに注意してください。
自動再入力をサポートするユーザーエージェントですでに行われているのと同様に、ユーザーエージェントは、
新しいフォームフィールドに入力する前に、引き続きユーザーの同意を考慮するべきです。
6.1. サードパーティの自動入力プロバイダー
ブラウザー拡張機能およびサードパーティの自動入力プロバイダー(パスワードマネージャーなど)は、
同じ構造を持つAutofillEventを構築して配送することにより、
このAPIを利用でき、
自動入力元にかかわらず一貫した動作を保証できます。