1. はじめに
Web Printing API は、隔離コンテキストで印刷機能を実装するために、前例のない柔軟性をもたらします。この API は通常の Web コンテキストでは公開されません。
1.1. 既存の代替手段
既存の
window.
メソッドはありますが、基本的には
印刷ダイアログを開き、残りの操作をユーザーに求めます。Web Printing API は、
アプリ開発者が、隔離コンテキスト内の Web アプリケーションから、
オペレーティングシステムでローカルに利用可能なプリンターへ直接アクセスできるようにし、
カスタム印刷属性(用紙サイズ、色設定、品質など)を指定して
印刷ジョブを送信できるようにします。
print()
1.2. Web Printing API の機能
Web Printing API を使用すると、次のことができます。
-
ダイアログなしで、コードから直接印刷ジョブを送信できます。
-
独自の印刷ダイアログを実装できます。
-
ユーザー操作なしで、カスタム印刷属性を指定して印刷できます。
-
プリンターを一覧表示し、プリンターの機能や プリンター状態(アイドル、ビジーなど)を取得できます。 プリンターの機能がわかっていれば、アプリは特定の印刷属性を持つ 印刷準備済みファイルを作成できます。
-
任意の方法で印刷を自動化できます。これまで反復的だった印刷 ワークフローを構築できます。
-
さらに、すべてに加えて、
window.とは異なり、印刷ジョブが完了したか、 失敗したかなど、印刷ジョブのジョブ状態を監視できます。print()
RFC8011 の第 5 節は、さらに詳しく知るうえで特に有用です (https://datatracker.ietf.org/doc/html/rfc8011#section-5)。
2. 例
2.1. プリンターと基本属性の一覧表示
try { const printers= await printing. getPrinters(); for ( const printerof printers) { const attributes= printer. cachedAttributes(); console. log( $attributes { printerName . には次の } 基本 ( 属性があります ) $ : attributes { } ); } } catch ( err) { console. warn( "印刷操作に失敗しました: " + err); }
2.2. プリンターと詳細属性の一覧表示
try { const printers= await printing. getPrinters(); const promises= printers. map( printer=> printer. fetchAttributes()); Promise. all( promises). then(( values) => { for ( const attributesof values) { console. log( $attributes { printerName . には次の } 詳細 ( 属性があります ) $ : attributes { } ); } }); } catch ( err) { console. warn( "印刷操作に失敗しました: " + err); }
2.3. プリンター状態の照会
try { const printers= await printing. getPrinters(); const printer= printers. find( printer=> printer. cachedAttributes(). printerName=== 'Brother QL-820NWB' ); const attributes= await printer. fetchAttributes(); console. log( $attributes { printerName . の } 状態は $ 新しい attributes { printerState . です } ! ); } catch ( err) { console. warn( "印刷操作に失敗しました: " + err); }
2.4. 印刷ジョブの送信
try { const printers= await printing. getPrinters(); const printer= printers. find( printer=> printer. cachedAttributes(). printerName=== 'Brother QL-820NWB' ); const printJob= await printer. submitPrintJob( "サンプル印刷ジョブ" , new Blob(...), { copies: 2 , media: 'iso_a4_210x297mm' , multipleDocumentHandling: 'separate-documents-collated-copies' , printerResolution: { crossFeedDirectionResolution: 300 , feedDirectionResolution: 400 , units: 'dots-per-inch' }, sides: 'one-sided' , printQuality: 'high' , pageRanges: [{ from : 1 , to: 5 }, { from : 7 , to: 10 }], }); const printJobComplete= new Promise(( resolve, reject) => { printJob. onjobstatechange= () => { const jobState= printJob. attributes(). jobState; if ( IsErrorStatus( jobState)) { console. warn( ジョブでエラーが発生しました$ : jobState { } ); reject( /**/ ); return ; } if ( jobState=== "completed" ) { console. log( "ジョブが完了しました!" ); resolve( /**/ ); return ; } console. log( ジョブ状態が $jobState { に変更されました } ); }; }); await printJobComplete; } catch ( err) { console. warn( "印刷操作に失敗しました: " + err); }
2.5. 印刷ジョブのキャンセル
try { const printers= await printing. getPrinters(); const printer= printers. find( printer=> printer. cachedAttributes(). printerName=== 'Brother QL-820NWB' ); const printJob= await printer. submitPrintJob(...); // ジョブがすでに完了している場合、これは効果がない可能性があります。 printJob. cancel(); } catch ( err) { console. warn( "印刷操作に失敗しました: " + err); }
3. Window
インターフェイスへの拡張
[Exposed =Window ,SecureContext ,IsolatedContext ]partial interface Window { [SameObject ]readonly attribute WebPrintingManager ; };printing
各 Window
オブジェクトは、WebPrintingManager
オブジェクトの一意のインスタンスに関連付けられます。このインスタンスは、Window
オブジェクトが作成されるときに割り当てられます。
4.
WebPrintingManager
[Exposed =Window ,SecureContext ,IsolatedContext ]interface {WebPrintingManager Promise <sequence <WebPrinter >>(); };getPrinters
このインターフェイス上のメソッドは、その手順の一部を並列に実行し、 Web 印刷タスクソースを介してメインスレッドへタスクをキューに入れます。
getPrinters()
メソッドの手順は次のとおりです。
-
this の 関連するグローバルオブジェクトの 関連付けられた Document が、"web-printing" という名前の ポリシー制御機能の使用を許可されていない場合、"
NotAllowedError"DOMExceptionを投げる。 -
promise を新しい promise とする。
-
global を this の関連するグローバルオブジェクトとする。
-
次の手順を並列に実行する。
-
local_printers を、オペレーティングシステムでローカルに利用可能なすべてのプリンターとする。
-
attributes_list を、
WebPrinterAttributes辞書の空のリストとする。 -
local_printers の各 printer について反復する。
-
web_printer_attributes を新しい
WebPrinterAttributes辞書とする。 -
web_printer_attributes の
printerNameを printer の名前に設定する。 -
web_printer_attributes の
printerIdを printer の id に設定する。この id は、それ自体の SHA256 ハッシュの 16 進文字列表現を返すことで難読化されなければなりません。 -
web_printer_attributes を attributes_list に追加する。
-
-
global 上で、Web 印刷タスクソースを使用してグローバルタスクをキューに入れ、次の 手順を実行する。
-
web_printers を、
WebPrinterオブジェクトの空のリストとする。 -
attributes_list の各 attributes について反復する。
-
web_printer を新しい
WebPrinterとし、そのattributes を attributes に設定する。 -
web_printer を web_printers に追加する。
-
-
promise を web_printers で解決する。
-
-
-
promise を返す。
5. WebPrinter
[Exposed =Window ,SecureContext ,IsolatedContext ]interface {WebPrinter WebPrinterAttributes ();cachedAttributes Promise <WebPrinterAttributes >();fetchAttributes Promise <WebPrintJob >(submitPrintJob USVString ,job_name Blob ,document_data optional WebPrintJobTemplateAttributes = {}); };template_attributes
各 WebPrinter
は attributes を持ちます。これは
WebPrinterAttributes
のインスタンスであり、初期状態では
printerName
と printerId
のみを含みます。さらに多くの情報を取得するには、fetchAttributes()
を使用する必要があります。
cachedAttributes()
メソッドは attributes を返します。
fetchAttributes()
メソッドの手順は次のとおりです。
-
promise を新しい promise とする。
-
次の手順を並列に実行する。
-
プリンターとの通信中に何らかの問題がある場合、promise を新しい
NetworkErrorDOMExceptionで拒否し、これらの手順を中止する。 -
new_web_printer_attributes を
WebPrinterAttributesの新しいインスタンスとする。 -
プリンター機能についてプリンターに照会する。printer_capabilities を返された機能のリストとする。
-
printer_capabilities の各 printer_capability について反復する。
-
Internet Printing Protocol(RFC 8011)に従って、printer_capability を
WebPrinterAttributes辞書に適合させるために必要なマッピングを実行する。 -
対応する new_web_printer_attributes のフィールドに、マッピングされた printer_capability を設定する(例: media source に関連する printer_capability は、
mediaSourceDefaultおよびmediaSourceSupportedの有効な値にマッピングする必要がある)。 -
プリンター状態についてプリンターに照会する。返されたプリンター状態値を、new_web_printer_attributes の
printerStateに設定する。 -
attributes を new_web_printer_attributes に設定する。
-
promise を new_web_printer_attributes で解決する。
-
-
promise を返す。
submitPrintJob()
メソッドの手順は次のとおりです。
-
promise を新しい promise とする。
-
次の手順を並列に実行する。
-
プリンターとの通信中に何らかの問題がある場合、promise を新しい
NetworkErrorDOMExceptionで拒否し、これらの手順を中止する。 -
fetchAttributes()のアルゴリズムを使用して、attributes を更新する。 -
printer を、
submitPrintJob()が実行されているWebPrinterのインスタンスとする。 -
template_attributesの各 template_attribute について反復する。 -
template_attribute が、対応する printer のattributes と照合して確認されるサポート済み値を含まない場合(例:
mediaSourceをmediaSourceSupportedと照合する)、 promise を新しいDataErrorDOMExceptionで拒否し、これらの手順を中止する。 -
pdf_data に PDF 文書データを保持させる。
document_dataBlobを PDF 文書に変換し、pdf_data の値として設定する。document_dataが不正な形式、すなわち有効な PDF 文書でない場合、promise を新しいDataErrorDOMExceptionで拒否し、これらの手順を中止する。 -
pdf_data を
WebPrintJobTemplateAttributesとともに送信し、プリンターへ印刷ジョブとして送信する。 -
print_job を
WebPrintJobインターフェイスのインスタンスとする。print_job を、プリンターへ送信されたばかりの印刷ジョブに関連付ける。
-
-
promise を print_job で解決する。
-
promise を返す。
6. WebPrintJob
[Exposed =Window ,SecureContext ,IsolatedContext ]interface :WebPrintJob EventTarget {WebPrintJobAttributes ();attributes undefined ();cancel attribute EventHandler ; };onjobstatechange
各 WebPrintJob
は attributes を持ちます。これは
WebPrintJobAttributes
のインスタンスであり、初期状態では空です。
attributes()
メソッドは、印刷ジョブがどの状態にあるか(例: 完了したページ数)を示す attributes を返します。
cancel()
メソッドは印刷ジョブをただちに中止します。
signal
パラメーターとして型 AbortSignal
を渡すことでも実現できます。これは
submitPrintJob()
メソッドを呼び出すときに、WebPrintJobTemplateAttributes
の一部として渡されます。
onjobstatechange
は、onjobstatechange
イベント型のイベントハンドラー IDL 属性です。
ユーザー
エージェントは、
印刷ジョブの WebPrintJobState
または jobPagesCompleted
が変更されるたびに、onjobstatechange
イベントを発火しなければなりません。
7. データモデル
WebPrinterAttributes
- attributes
を表す辞書。
WebPrintJobTemplateAttributes
- 印刷ジョブ属性を表す辞書。
dictionary {WebPrinterAttributes USVString ;printerName USVString ;printerId unsigned long ;copiesDefault WebPrintingRange ;copiesSupported WebPrintingMediaCollection ;mediaColDefault sequence <WebPrintingMediaCollection >;mediaColDatabase USVString ;mediaSourceDefault sequence <USVString >;mediaSourceSupported WebPrintingMimeMediaType ;documentFormatDefault sequence <WebPrintingMimeMediaType >;documentFormatSupported WebPrintingMultipleDocumentHandling ;multipleDocumentHandlingDefault sequence <WebPrintingMultipleDocumentHandling >;multipleDocumentHandlingSupported WebPrintingOrientationRequested ;orientationRequestedDefault sequence <WebPrintingOrientationRequested >;orientationRequestedSupported WebPrintingResolution ;printerResolutionDefault sequence <WebPrintingResolution >;printerResolutionSupported WebPrintColorMode ;printColorModeDefault sequence <WebPrintColorMode >;printColorModeSupported WebPrinterState ;printerState USVString ;printerStateMessage sequence <WebPrinterStateReason >;printerStateReasons WebPrintQuality ;printQualityDefault sequence <WebPrintQuality >;printQualitySupported WebPrintingSides ;sidesDefault sequence <WebPrintingSides >; };sidesSupported dictionary {WebPrintJobTemplateAttributes unsigned long ;copies WebPrintingMediaCollectionRequested ;mediaCol USVString ;mediaSource WebPrintingMultipleDocumentHandling ;multipleDocumentHandling WebPrintingOrientationRequested ;orientationRequested WebPrintingResolution ;printerResolution WebPrintColorMode ;printColorMode WebPrintQuality ;printQuality WebPrintingSides ;sides AbortSignal ; };signal dictionary {WebPrintingRange unsigned long ;from unsigned long ; };to dictionary {WebPrintingResolution unsigned long ;crossFeedDirectionResolution unsigned long ;feedDirectionResolution WebPrintingResolutionUnits ; };units typedef (WebPrintingRange or unsigned long );WebPrintingMediaSizeDimension dictionary {WebPrintingMediaSize WebPrintingMediaSizeDimension ;yDimension WebPrintingMediaSizeDimension ; };xDimension dictionary {WebPrintingMediaCollection USVString ;mediaSizeName WebPrintingMediaSize ; };mediaSize dictionary {WebPrintingMediaSizeRequested required unsigned long ;yDimension required unsigned long ; };xDimension dictionary {WebPrintingMediaCollectionRequested required WebPrintingMediaSizeRequested ; };mediaSize dictionary {WebPrintJobAttributes USVString ;jobName unsigned long ;jobPages unsigned long ;jobPagesCompleted WebPrintJobState ; };jobState enum {WebPrintingMimeMediaType , };"application/pdf" enum {WebPrintingMultipleDocumentHandling ,"separate-documents-collated-copies" , };"separate-documents-uncollated-copies" enum {WebPrintingOrientationRequested ,"portrait" , };"landscape" enum {WebPrintingResolutionUnits ,"dots-per-inch" , };"dots-per-centimeter" enum {WebPrintingSides ,"one-sided" ,"two-sided-long-edge" , };"two-sided-short-edge" enum {WebPrintQuality ,"draft" ,"normal" , };"high" enum {WebPrintColorMode ,"color" , };"monochrome" enum {WebPrinterState ,"idle" ,"processing" , };"stopped" enum {WebPrinterStateReason ,"none" ,"other" ,"connecting-to-device" ,"cover-open" ,"developer-empty" ,"developer-low" ,"door-open" ,"fuser-over-temp" ,"fuser-under-temp" ,"input-tray-missing" ,"interlock-open" ,"interpreter-resource-unavailable" ,"marker-supply-empty" ,"marker-supply-low" ,"marker-waste-almost-full" ,"marker-waste-full" ,"media-empty" ,"media-jam" ,"media-low" ,"media-needed" ,"moving-to-paused" ,"opc-life-over" ,"opc-near-eol" ,"output-area-almost-full" ,"output-area-full" ,"output-tray-missing" ,"paused" ,"shutdown" ,"spool-area-full" ,"stopped-partly" ,"stopping" ,"timed-out" ,"toner-empty" ,"toner-low" , };"cups-pki-expired" enum {WebPrintJobState ,"preliminary" ,"pending" ,"processing" ,"completed" ,"canceled" };"aborted"
8. プライバシーとセキュリティに関する考慮事項
8.1. 潜在的な問題
8.1.1. フィンガープリンティング
WebPrinter
オブジェクトは、フィンガープリンティングに使用できる
printerName
および printerId
attributes
を公開します。
8.1.2. 印刷ジョブの偽造
悪意のあるコード注入は、次の事態を引き起こす可能性があります。
-
望ましくない印刷ジョブがプリンターへ送信されること、
-
プリンターに対するサービス拒否攻撃。
これは隔離コンテキストでは決して発生してはなりません。
8.1.3. 監視
アプリケーションは、プリンターが使用中である時点を潜在的に観測できる可能性があります。
8.2. 緩和要因
8.2.1. 権限ポリシー
この仕様は、文字列 "web-printing" によって識別されるポリシー制御機能を定義します。
そのデフォルト許可リストは "self" です。
文書の権限ポリシーは、
その文書内の任意のコンテンツが getPrinters()
を使用できるかどうかを決定します。
いずれかの文書で無効化されている場合、その文書内のどのコンテンツも
getPrinters()
を使用することを許可されません。
8.2.2. ユーザーの同意
プリンターへのアクセスは強力な機能です。ユーザーエージェントは、
明示的な許可なしに、
Web アプリケーションが WebPrinter
オブジェクトへのアクセスを取得することを許可してはなりません。
ユーザーの同意は、特定の オリジンについて取得されなければなりません。
同意の要求は、
getPrinters()
メソッドの呼び出しによってトリガーされなければなりません。ユーザーエージェントは、
どのオリジンがアクセスを要求しているかを明確に示し、
ユーザーが十分な情報に基づいた判断を下せるだけの情報を提供する権限プロンプトを表示しなければなりません。
ユーザーエージェントは、一時的な権限 (例:「このセッションのみ」)と永続的な権限の両方のオプションを提供するべきです。 ユーザーが永続的な アクセスを許可したことを忘れるリスクを緩和するため、一時的な権限をデフォルトかつより目立つオプションにするべきです。
ユーザーには、この API に対して以前に 付与された権限を表示および取り消すための仕組みが提供されなければなりません。