Web 印刷 API

非公式提案ドラフト,

このバージョン:
https://github.com/bylica-at-google/web-printing-api
課題追跡:
GitHub
編集者:
Dominik Bylica (Google)

概要

この文書は、アプリ開発者が隔離コンテキスト内のプリンターへ直接アクセスできるようにすることで、すばらしい プリンター関連機能を構築できるようにする新しい Web Printing API を定義します。

この文書のステータス

この仕様は、Web Platform Incubator Community Group によって公開されました。 これは W3C 標準ではなく、W3C 標準化過程上のものでもありません。 W3C Community Contributor License Agreement (CLA) の下では、限定的なオプトアウトおよびその他の条件が適用されることに注意してください。 W3C Community and Business Groups について詳しく学んでください。

1. はじめに

Web Printing API は、隔離コンテキストで印刷機能を実装するために、前例のない柔軟性をもたらします。この API は通常の Web コンテキストでは公開されません。

1.1. 既存の代替手段

既存の window.print() メソッドはありますが、基本的には 印刷ダイアログを開き、残りの操作をユーザーに求めます。Web Printing API は、 アプリ開発者が、隔離コンテキスト内の Web アプリケーションから、 オペレーティングシステムでローカルに利用可能なプリンターへ直接アクセスできるようにし、 カスタム印刷属性(用紙サイズ、色設定、品質など)を指定して 印刷ジョブを送信できるようにします。

1.2. Web Printing API の機能

Web Printing API を使用すると、次のことができます。

Web Printing API は Internet Printing Protocol をモデルにしています。 つまり、プリンター機能および印刷属性は、 その名前、可能な値、有効な値のすべてが、 Internet Printing Protocol(RFC8011)を定義する標準文書内の 定義に由来します。

RFC8011 の第 5 節は、さらに詳しく知るうえで特に有用です (https://datatracker.ietf.org/doc/html/rfc8011#section-5)。

2.

2.1. プリンターと基本属性の一覧表示

try {
  const printers = await printing.getPrinters();
  for (const printer of 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 attributes of 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() メソッドの手順は次のとおりです。
  1. this関連するグローバルオブジェクト関連付けられた Document が、"web-printing" という名前の ポリシー制御機能の使用を許可されていない場合、"NotAllowedError" DOMException投げる

  2. promise新しい promise とする。

  3. globalthis関連するグローバルオブジェクトとする。

  4. 次の手順を並列に実行する。

    1. local_printers を、オペレーティングシステムでローカルに利用可能なすべてのプリンターとする。

    2. attributes_list を、WebPrinterAttributes 辞書の空のリストとする。

    3. local_printers の各 printer について反復する

      1. web_printer_attributes を新しい WebPrinterAttributes 辞書とする。

      2. web_printer_attributesprinterNameprinter の名前に設定する。

      3. web_printer_attributesprinterIdprinter の id に設定する。この id は、それ自体の SHA256 ハッシュの 16 進文字列表現を返すことで難読化されなければなりません。

      4. web_printer_attributesattributes_list に追加する。

    4. global 上で、Web 印刷タスクソースを使用してグローバルタスクをキューに入れ、次の 手順を実行する。

      1. web_printers を、WebPrinter オブジェクトの空のリストとする。

      2. attributes_list の各 attributes について反復する

        1. web_printer を新しい WebPrinter とし、そのattributesattributes に設定する。

        2. web_printerweb_printers に追加する。

      3. promiseweb_printers解決する

  5. 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 = {});
};

WebPrinterattributes を持ちます。これは WebPrinterAttributes のインスタンスであり、初期状態では printerNameprinterId のみを含みます。さらに多くの情報を取得するには、fetchAttributes() を使用する必要があります。

cachedAttributes() メソッドは attributes を返します。

fetchAttributes() メソッドの手順は次のとおりです。
  1. promise新しい promise とする。

  2. 次の手順を並列に実行する。

    1. プリンターとの通信中に何らかの問題がある場合、promise を新しい NetworkError DOMException拒否し、これらの手順を中止する。

    2. new_web_printer_attributesWebPrinterAttributes の新しいインスタンスとする。

    3. プリンター機能についてプリンターに照会する。printer_capabilities を返された機能のリストとする。

    4. printer_capabilities の各 printer_capability について反復する

    5. Internet Printing Protocol(RFC 8011)に従って、printer_capabilityWebPrinterAttributes 辞書に適合させるために必要なマッピングを実行する。

    6. 対応する new_web_printer_attributes のフィールドに、マッピングされた printer_capability を設定する(例: media source に関連する printer_capability は、mediaSourceDefault および mediaSourceSupported の有効な値にマッピングする必要がある)。

    7. プリンター状態についてプリンターに照会する。返されたプリンター状態値を、new_web_printer_attributesprinterState に設定する。

    8. attributesnew_web_printer_attributes に設定する。

    9. promisenew_web_printer_attributes解決する

  3. promise を返す。

submitPrintJob() メソッドの手順は次のとおりです。
  1. promise新しい promise とする。

  2. 次の手順を並列に実行する。

    1. プリンターとの通信中に何らかの問題がある場合、promise を新しい NetworkError DOMException拒否し、これらの手順を中止する。

    2. fetchAttributes() のアルゴリズムを使用して、attributes を更新する。

    3. printer を、submitPrintJob() が実行されている WebPrinter のインスタンスとする。

    4. template_attributes の各 template_attribute について反復する

    5. template_attribute が、対応する printerattributes と照合して確認されるサポート済み値を含まない場合(例: mediaSourcemediaSourceSupported と照合する)、 promise を新しい DataError DOMException拒否し、これらの手順を中止する。

    6. pdf_data に PDF 文書データを保持させる。document_data Blob を PDF 文書に変換し、pdf_data の値として設定する。document_data が不正な形式、すなわち有効な PDF 文書でない場合、promise を新しい DataError DOMException拒否し、これらの手順を中止する。

    7. pdf_dataWebPrintJobTemplateAttributes とともに送信し、プリンターへ印刷ジョブとして送信する。

    8. print_jobWebPrintJob インターフェイスのインスタンスとする。print_job を、プリンターへ送信されたばかりの印刷ジョブに関連付ける。

  3. promiseprint_job解決する

  4. promise を返す。

signalAbortSignal は、印刷ジョブを cancel() するためにも使用できます。

6. WebPrintJob

[Exposed=Window, SecureContext, IsolatedContext]
interface WebPrintJob : EventTarget {
  WebPrintJobAttributes attributes();
  undefined cancel();

  attribute EventHandler onjobstatechange;
};

WebPrintJobattributes を持ちます。これは 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. 緩和要因

IDL は、この API が隔離コンテキストでのみ公開されることを義務付けています。

8.2.1. 権限ポリシー

この仕様は、文字列 "web-printing" によって識別されるポリシー制御機能を定義します。 そのデフォルト許可リスト"self" です。

文書権限ポリシーは、 その文書内の任意のコンテンツが getPrinters() を使用できるかどうかを決定します。 いずれかの文書で無効化されている場合、その文書内のどのコンテンツも getPrinters()使用することを許可されません

プリンターへのアクセスは強力な機能です。ユーザーエージェントは、 明示的な許可なしに、 Web アプリケーションが WebPrinter オブジェクトへのアクセスを取得することを許可してはなりません。

ユーザーの同意は、特定の オリジンについて取得されなければなりません。 同意の要求は、 getPrinters() メソッドの呼び出しによってトリガーされなければなりません。ユーザーエージェントは、 どのオリジンがアクセスを要求しているかを明確に示し、 ユーザーが十分な情報に基づいた判断を下せるだけの情報を提供する権限プロンプトを表示しなければなりません。

ユーザーエージェントは、一時的な権限 (例:「このセッションのみ」)と永続的な権限の両方のオプションを提供するべきです。 ユーザーが永続的な アクセスを許可したことを忘れるリスクを緩和するため、一時的な権限をデフォルトかつより目立つオプションにするべきです。

ユーザーには、この API に対して以前に 付与された権限を表示および取り消すための仕組みが提供されなければなりません。

適合性

文書の 慣例

適合性要件は、 説明的な表明と RFC 2119 の用語の組み合わせによって表現されます。 この文書の規範的な部分におけるキーワード “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” は、RFC 2119 に記述されているように解釈されます。 ただし、読みやすさのため、 この仕様ではこれらの語がすべて大文字で現れるとは限りません。

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

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

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

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

Note, これは参考注記です。

索引

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

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

参考文献

規範的参考文献

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[FileAPI]
Marijn Kruisselbrink. File API. URL: https://w3c.github.io/FileAPI/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[ISOLATED-CONTEXTS]
Isolated Contexts. Draft Community Group Report. URL: https://wicg.github.io/isolated-web-apps/isolated-contexts.html
[PERMISSIONS]
Marcos Caceres; Mike Taylor. Permissions. URL: https://w3c.github.io/permissions/
[PERMISSIONS-POLICY-1]
Ian Clelland. Permissions Policy. URL: https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

IDL 索引

[Exposed=Window, SecureContext, IsolatedContext]
partial interface Window {
  [SameObject] readonly attribute WebPrintingManager printing;
};

[Exposed=Window, SecureContext, IsolatedContext]
interface WebPrintingManager {
  Promise<sequence<WebPrinter>> getPrinters();
};

[Exposed=Window, SecureContext, IsolatedContext]
interface WebPrinter {
  WebPrinterAttributes cachedAttributes();
  Promise<WebPrinterAttributes> fetchAttributes();
  Promise<WebPrintJob> submitPrintJob(
    USVString job_name,
    Blob document_data,
    optional WebPrintJobTemplateAttributes template_attributes = {});
};

[Exposed=Window, SecureContext, IsolatedContext]
interface WebPrintJob : EventTarget {
  WebPrintJobAttributes attributes();
  undefined cancel();

  attribute EventHandler onjobstatechange;
};

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"
};