自動入力イベント

コミュニティグループ報告書草案

このバージョン:
https://wicg.github.io/autofill-event/
課題追跡:
GitHub
編集者:
Shopify

概要

この仕様は、ユーザーエージェントがフォームフィールドを自動入力しようとするときに発火するイベントを定義し、 開発者が自動入力される値に基づいてフォームを動的に適応できるようにします。

この文書の位置付け

この仕様は、Web Platform Incubator Community Groupによって公開されました。 これはW3C標準ではなく、W3C標準化過程にもありません。 以下の W3Cコミュニティ貢献者ライセンス契約 (CLA) には、限定的なオプトアウトがあり、その他の条件も適用されることに注意してください。 W3Cコミュニティグループおよびビジネスグループについて詳しく知ることができます。

1. はじめに

この節は非規範的です。

自動入力は、日々何百万人ものユーザーの手間を軽減する、Webの重要な機能です。 ログイン画面、電子商取引、連絡先フォームなどで広く使用されています。 特に商取引および購入手続きのフローでは、自動入力は購入者の体験と販売者の成果の両方に 大きな利点をもたらします。

同時に、Webの自動入力には、部分的または不完全な入力、 ブラウザー間の相互運用性の問題、開発者にとって実装および保守のコストが高いことなど、いくつかの欠点があります。

重要な例の1つは住所の自動入力です。これは正しく実装された場合、動的なフォームになります。 地域によって、住所入力の形式や要件は異なります。国を選択するには、 フォームを変更(フィールドの並べ替え、追加、削除)する必要があり、ユーザーからの入力に 依存しますが、自動入力がこの対話を仲介するため、レンダリングされたフォームに 正しく応答しない場合があります。

現在の「業界標準」の解決策では、適切な情報を予測して 取得し、それをユーザーに提示しようとする非表示のフォームフィールドを使用する必要があります。この解決策は壊れやすく、 複雑です。さらに悪いことに、正当なユースケースを実現するための非表示フィールドの使用を定着させますが、同じ 手法は悪意ある者によって悪用される可能性があり、実際に悪用されています。

この仕様は、自動入力値が フォームフィールドに確定される前に発火するAutofillEvent を導入し、開発者が次のことを行えるようにします。

  1. 自動入力されようとしている値を調査する

  2. それらの値に基づいてフォームを動的に適応させる(たとえば、国固有の住所フィールドを表示する)

  3. フォームが自動入力値を受け入れる準備ができた時点をユーザーエージェントに通知する

1.1. 目標

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. 自動入力値エントリー

自動入力値 エントリーは、次の要素からなるタプルです。

  1. HTMLElement — 自動入力値を受け取るフォームコントロール

  2. 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;
// AutofillValueEntryは[HTMLElement, DOMString]のタプルである
// 最初の要素はフォームコントロールであり、2番目の要素は入力する値である

AutofillEvent インターフェイスは、ユーザーエージェントがフォームフィールドを自動入力しようとするときに 配送されるイベントを表します。

3.1. 属性

autofillValues属性は、 自動入力値 エントリーのリストを返します。各エントリーは、最初の要素がHTMLElement (入力対象となるフォームコントロール)であり、2番目の要素がDOMString (入力する値)であるタプルです。

refill属性は、RefillCallback または nullを返します。nullでない場合、このコールバックを呼び出すとPromise が返され、これを待機すると、 フォーム構造が変更され、自動入力を再試行すべきことがユーザーエージェントに通知されます。

refill 属性は、次の場合にnullとなります。

これにより、ページがフォームを継続的に変更して再入力を要求する無限ループを防止します。

AutofillEvent には、関連付けられた自動入力値リスト自動入力値 エントリーリスト)があり、初期状態では空のリストです。

AutofillEvent には、関連付けられた再入力許可フラグ真偽値)があり、 初期値はtrueです。

AutofillEvent には、関連付けられた配送タイムスタンプDOMHighResTimeStamp)があり、 初期値は0です。

AutofillEvent には、関連付けられた再入力保留フラグ真偽値)があり、 初期値はfalseです。

4. 処理モデル

4.1. 自動入力イベントの発火

文書document自動入力値エントリーリスト entries、および真偽値allowRefillを指定して、自動入力 イベントを発火するには、次の手順を実行します。
  1. AutofillEventを使用してイベントを作成した結果を、eventとします。

  2. eventtype 属性を「autofill」に初期化します。

  3. eventbubbles 属性をtrueに初期化します。

  4. eventcancelable 属性をfalseに初期化します。

  5. event自動入力値リストentriesに設定します。

  6. event再入力許可フラグallowRefillに設定します。

  7. event配送タイムスタンプ現在の高分解能時刻に設定します。

  8. documentに対してevent配送します。

  9. documentに対して、entriesを使用して自動入力操作を実行します。

注: 自動入力操作は、イベントが配送された直後に実行されます。 refill コールバックにより、ページはフォーム構造を変更した後、 実装定義のタイムアウト期間内に追加の自動入力処理を要求できます。

4.2. 再入力要求の処理

AutofillEvent eventを指定して再入力 要求を処理するには、次の手順を実行します。
  1. 現在の高分解能時刻nowとします。

  2. nowからevent配送タイムスタンプを引いた値を、elapsedとします。

  3. 実装定義の期間をrefillTimeoutとします。

  4. elapsedrefillTimeoutより大きい場合は、「InvalidStateErrorDOMException拒否されたPromiseを返します。

  5. event再入力許可フラグがfalseの場合は、「InvalidStateErrorDOMException拒否されたPromiseを返します。

  6. event再入力保留フラグがtrueの場合は、「InvalidStateErrorDOMException拒否されたPromiseを返します。

  7. event再入力保留フラグをtrueに設定します。

  8. 新しい Promisepromiseとします。

  9. eventに関連する文書documentとします。

  10. promiseを返し、並行して次の手順を実行します。

    1. 更新された自動入力値 エントリー(変更されたフォームに対してユーザーの自動入力データを再照合したもの)をentriesとします。

    2. 次の処理を行うタスクをキューに追加します。

      1. documententries、およびfalseを指定して、自動入力イベントを発火します。

      2. documentに対して、entriesを使用して自動入力操作を実行します。

      3. 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を利用でき、 自動入力元にかかわらず一貫した動作を保証できます。

適合性

文書の 表記規則

適合要件は、説明的な表明と RFC 2119の用語を組み合わせて 表現されます。 この文書の規範的な部分におけるキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、 「MAY」、および「OPTIONAL」は、 RFC 2119に記載されているとおりに 解釈されるものとします。 ただし、読みやすさのため、 この仕様ではこれらの語が常に大文字で表記されるわけではありません。

明示的に非規範的と示された節、例、および注を除き、 この仕様のすべてのテキストは規範的です。 [RFC2119]

この仕様の例は、「たとえば」という語で導入されるか、 規範的なテキストから class="example"によって区別されます。 次のようになります。

これは参考例の一例です。

参考注記は「注」という語で始まり、 規範的なテキストから class="note"によって区別されます。 次のようになります。

注: これは参考注記です。

索引

この仕様で定義される 用語

参照によって定義される 用語

参考文献

規範的参考文献

[DOM]
Anne van Kesteren。 DOM標準。現行標準。 URL: https://dom.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss。 高分解能時刻。URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren、ほか。 HTML標準。 現行標準。URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren、Domenic Denicola。 Infra 標準。現行標準。URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner。 RFCで要件レベルを 示すために使用するキーワード。1997年3月。現行の最良の慣行。URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen、Timothy Gu。 Web IDL標準。現行 標準。URL: https://webidl.spec.whatwg.org/

IDL索引

[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;
// AutofillValueEntryは[HTMLElement, DOMString]のタプルである
// 最初の要素はフォームコントロールであり、2番目の要素は入力する値である