この仕様は、ウェブサイトが自身をウェブ共有ターゲットとして宣言できるようにする API を定義する。ウェブ共有ターゲットは、[[[Web-Share]]]、またはシステムイベント (例えば、ネイティブアプリからの共有)から共有コンテンツを受け取ることができる。
これは {{NavigatorContentUtils/registerProtocolHandler()}} と似た仕組みであり、 ユーザーエージェントにウェブサイトを登録しておき、後で別のサイトまたは ネイティブアプリケーションから、ユーザーエージェントを介して(場合によっては ユーザーの裁量で)呼び出されるようにする点で同様である。違いは、 {{NavigatorContentUtils/registerProtocolHandler()}} がプログラム的な API によって ハンドラーを登録するのに対し、Web Share Target は [[[appmanifest]]] 内で宣言され、 ユーザーエージェントまたはユーザーが選択する時点で登録される点である。
これは Web Share Target 仕様の初期ドラフトである。
この API を実装するためには、ユーザーエージェントは [[[appmanifest]]] を サポートしなければならない(MUST)。この仕様は [[[Web-Share]]] 仕様の一部の 定義も再利用する。ただし、[[[Web-Share]]] のサポートは任意である(OPTIONAL)。
サイトを共有ターゲットとして登録するには、次のように、[=manifest/share_target=] エントリーを [[[appmanifest]]] に追加する。
{
"name": "Includinator",
"share_target": {
"action": "share.html",
"params": {
"title": "name",
"text": "description",
"url": "link"
}
}
}
[=ShareTarget/params=] のキーは [[[Web-Share]]] の {{ShareData}} における キー名に対応し、その値は、ターゲットが起動されたときにクエリパラメーターとして 使用される任意の名前である。
共有が行われ、ユーザーがこの共有ターゲットを選択した場合、ユーザーエージェントは HTML フォーム送信と同様に、共有データを含むクエリパラメーター値を付けて、 `action` URL に新しい閲覧コンテキストを開く。
この例では、マニフェストが `https://example.org/includinator/manifest.webmanifest` にあるものとする。
<html>
<link rel="manifest" href="manifest.webmanifest">
<script>
window.addEventListener('load', () => {
const parsedUrl = new URL(window.location);
const { searchParams } = parsedUrl;
console.log("Title shared:", searchParams.get('name'));
console.log("Text shared:", searchParams.get('description'));
console.log("URL shared:", searchParams.get('link'));
});
</script>
入ってくる共有にタイトル "My News" と URL `http://example.com/news` が含まれる場合、 ユーザーエージェントは新しいウィンドウまたはタブを開き、次へ移動する。
https://example.org/includinator/share.html?name=My+News&link=http%3A%2F%2Fexample.com%2Fnews
[=`application\/x-www-form-urlencoded`=] エンコーディングを使用するため、 U+0020(SPACE)文字は、予想されるかもしれない "`%20`" ではなく "`+`" として エンコードされる。処理系は、U+002B(+)文字を U+0020(SPACE)としてデコードするよう 注意しなければならない。ECMAScript の `decodeURIComponent` 関数を含む一部の URL デコードライブラリは、これを自動的には行わない場合がある。
クエリパラメーターには、共有される {{ShareData}} からの情報が設定される。 {{ShareData}} に特定のメンバーの情報が含まれない場合、そのクエリパラメーターは 省略される。
共有ターゲットは、{{ShareData}} メンバーの一部だけに関心を持つ場合がある。 この例では、`POST` リクエストとしてデータを受け取る共有ターゲットも示している。 リクエストが即時の副作用を引き起こす場合は、この方式にすべきである。
{
"name": "Bookmark",
"share_target": {
"action": "/bookmark",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"url": "link"
}
}
}
共有された情報は、サーバーへネットワーク越しに送信されるのではなく、 [=service worker=] によって読み取られる場合がある。
self.addEventListener("fetch", (event) => {
if (event.request.method !== "POST") {
event.respondWith(fetch(event.request));
return;
}
const formDataPromise = event.request.formData();
event.respondWith(
formDataPromise.then((formData) => {
const link = formData.get("link") || "";
saveBookmark(link);
return new Response(`Bookmark saved: ${link}`);
})
);
});
ハンドラーが共有データをどのように扱うかはハンドラーの裁量であり、 一般にはアプリの種類に依存する。いくつかの提案を以下に示す。
[=manifest=] は JSON であるため、 この仕様は [[JSON]] 仕様で定義される型、すなわち object と string に依存する。
次の手順を [=processing extension-point of web manifest=] に追加する。
マニフェストの share_target
メンバーは [=object=] である。存在する場合、このアプリケーションを
ウェブ共有ターゲットとして宣言し、アプリケーションが共有データを
どのように受け取るかを記述する。
ウェブ共有ターゲットは、 [=manifest/share_target=] メンバーを含む有効な [=manifest=] を持つウェブサイトである。
ウェブ共有ターゲットは、共有ターゲットの一種である(他の種類、 例えば一部のシステムアプリケーションも利用可能な場合がある)。
[=object=] |json:JSON| と [=ordered map=] |manifest:ordered map| が与えられたとき、 `share_target` メンバーを処理するには、次を実行する。
ShareTarget [=object=] は、次のメンバーを持つことができる。
action メンバー
method メンバー
enctype メンバー
params メンバー
ShareTargetParams [=object=] は、次のメンバーを持つことができる。
title
メンバー
text
メンバー
url メンバー
ウェブ共有ターゲットがいつどのように「登録」されるかは、ユーザーエージェント および/またはエンドユーザーの裁量に委ねられる。実際、 「登録」はユーザーエージェント固有の概念であり、ここでは正式には定義しない。 ユーザーエージェントはウェブ共有ターゲットを「登録」することを要求されない(NOT REQUIRED)。 ただし、エンドユーザーが選択したウェブ共有ターゲットへ共有データを伝達するための 何らかの仕組みを提供することだけは要求される。ユーザーエージェントは、ウェブ共有ターゲットが [=installed web application|installed=] されていない場合でも、それを「登録済み」と 見なしてもよい(MAY)。
ユーザーエージェントは、ユーザーがサイトを訪問した際にすべてのウェブ共有ターゲットを 自動的に登録してもよい(MAY)が、多数のターゲットの選択肢でユーザーを圧倒しないよう、 より慎重に判断することが推奨される(RECOMMENDED)。
ユーザーエージェントが採用できる登録戦略の例は次のとおりである。
エンドユーザーにウェブ共有ターゲットの一覧を提示する際、ユーザーエージェントは、 事前にマニフェストを索引付けしたオンラインサービスを使用してもよく、その結果、 ユーザーが一度も訪問したことがない、または明示的に登録したことがないターゲットを 表示してもよい。
ウェブ共有ターゲットは、エンドユーザーが汎用アプリケーション向けの何らかの データを共有しており、そのデータの受信者として特定のウェブ共有ターゲットを 示したときに、呼び出される。
データがどこから来るか、またエンドユーザーがどのようにウェブ共有ターゲットを 受信者として示すかは規定しない。ただし、考えられる一つの送信元は、 同じユーザーエージェント内の {{Navigator}} の {{Navigator/share()}} メソッドへの 呼び出しである。
ウェブ共有ターゲットの呼び出しにおける、その他の考えられる送信元の例は 次のとおりである。
ウェブ共有ターゲットが呼び出されたとき、そのデータは未規定の形式である 場合がある。ユーザーエージェントは、データがまだ {{ShareData}} オブジェクトでない場合、 まず、ホストシステムにおける同等の概念から `ShareData` のメンバーへマッピングすることにより、 そのデータを {{ShareData}} オブジェクトへ変換しなければならない(MUST)。 送信元が {{Navigator/share()}} への呼び出しであった場合、ユーザーエージェントは {{ShareData}} 引数を変更せずに使用すべきである(SHOULD)(ただし、別の形式を 経由して損失を伴う形で往復しなければならない場合があるため、常に可能とは限らない)。 ユーザーエージェントは、データを `ShareData` フィールドへできる限り適切に マッピングするためにヒューリスティックを用いてもよい(MAY)。
例えば、ホスト共有システムには専用の URL フィールドがなく、プレーンテキストと URL の両方が "text" フィールドで送信されることがある、という慣例を持つ場合がある。 Android ではこれが該当する。ユーザーエージェントは、"text" フィールドの全部または一部が [=valid URL string=] であるかを確認し、該当する場合、その部分を "text" フィールドから {{ShareData}} の {{ShareData/url}} メンバーへ移すことができる。
[=ordered map=] |manifest| を持つウェブ共有ターゲットが {{ShareData}} |data| で 呼び出されたとき、次の手順を実行する。
このアルゴリズムは、|manifest| に対して [=process the `share_target` member=] アルゴリズムが実行済みであり、その後も [=manifest/share_target=] を持っていることを前提としている。
この仕様には既知のアクセシビリティ上の考慮事項はない。
ウェブアプリの相互運用性ユースケースの基礎を築いた [[[WEBINTENTS]]] チームに感謝する。 特に、Web Share と Web Share Target の初期の普及活動に多大な尽力をした Paul Kinlan に感謝する。
この仕様の初期ドラフトを執筆し、API の設計とプロトタイプ作成に協力した Connie Pyromallis に感謝する。
この仕様の初期ドラフトにフィードバックを提供した Alex Russell と David Baron に 感謝する。