웹 인쇄 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는 일반 웹 컨텍스트에는 노출되지 않습니다.

1.1. 기존 대안

존재하는 window.print() 메서드가 있지만, 기본적으로 인쇄 대화 상자를 열고 나머지는 사용자가 하도록 요청합니다. Web Printing API는 앱 개발자가 격리된 컨텍스트의 웹 애플리케이션에서 운영체제에서 로컬로 사용할 수 있는 프린터에 직접 접근할 수 있게 해 주며, 사용자 지정 인쇄 속성(용지 크기, 색상 설정, 품질 등)으로 인쇄 작업을 제출할 수 있게 합니다.

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} has the following (basic) attributes: ${attributes});
  }
} catch (err) {
  console.warn("Printing operation failed: " + 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} has the following (detailed) attributes: ${attributes});
      }
    });
} catch (err) {
  console.warn("Printing operation failed: " + 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}'s new state is ${attributes.printerState}!);
} catch (err) {
  console.warn("Printing operation failed: " + 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("Sample Print Job",
    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(Job errored: ${jobState});
        reject(/**/);
        return;
      }
      if (jobState === "completed") {
        console.log("Job complete!");
        resolve(/**/);
        return;
      }
      console.log(Job state changed to ${jobState});
    };
  });
  await printJobComplete;
} catch (err) {
  console.warn("Printing operation failed: " + 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(...);

  // This might take no effect if the job has already finished.
  printJob.cancel();

} catch (err) {
  console.warn("Printing operation failed: " + 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 printing task source를 통해 메인 스레드에 작업을 다시 큐에 넣습니다.

getPrinters() 메서드 단계는 다음과 같습니다.
  1. this관련 전역 객체연결된 Document가 "web-printing"이라는 정책 제어 기능사용하도록 허용되지 않은 경우, "NotAllowedError" DOMExceptionthrow합니다.

  2. promise새 promise로 둡니다.

  3. globalthis관련 전역 객체로 둡니다.

  4. 다음 단계를 병렬로 실행합니다.

    1. local_printers를 운영체제에서 로컬로 사용할 수 있는 모든 프린터로 둡니다.

    2. attributes_listWebPrinterAttributes 딕셔너리의 빈 목록으로 둡니다.

    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 printing task source를 사용해 다음 단계를 실행합니다.

      1. web_printersWebPrinter 객체의 빈 목록으로 둡니다.

      2. attributes_list의 각 attributes에 대해 반복합니다.

        1. web_printerattributesattributes로 설정된 새 WebPrinter로 둡니다.

        2. web_printerweb_printers에 추가합니다.

      3. promiseweb_printersresolve합니다.

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

WebPrinter에는 attributes가 있으며, 이는 WebPrinterAttributes의 인스턴스입니다. 처음에는 printerNameprinterId만 포함하며, 더 많은 정보를 얻으려면 fetchAttributes()를 사용해야 합니다.

cachedAttributes() 메서드는 attributes를 반환합니다.

fetchAttributes() 메서드 단계는 다음과 같습니다.
  1. promise새 promise로 둡니다.

  2. 다음 단계를 병렬로 실행합니다.

    1. 프린터와 통신하는 동안 문제가 있는 경우, promise를 새 NetworkError DOMException으로 reject하고 이 단계를 중단합니다.

    2. new_web_printer_attributesWebPrinterAttributes의 새 인스턴스로 둡니다.

    3. 프린터에 프린터 기능을 쿼리합니다. 반환된 기능의 목록을 printer_capabilities로 둡니다.

    4. printer_capabilities의 각 printer_capability에 대해 반복합니다.

    5. Internet Printing Protocol(RFC 8011)에 따라 printer_capabilityWebPrinterAttributes 딕셔너리에 부합하도록 필요한 매핑을 수행합니다.

    6. 매핑된 printer_capabilitynew_web_printer_attributes의 해당 필드를 설정합니다(예: media source와 관련된 printer_capabilitymediaSourceDefaultmediaSourceSupported의 유효한 값으로 매핑되어야 합니다).

    7. 프린터에 프린터 상태를 쿼리합니다. new_web_printer_attributesprinterState를 반환된 프린터 상태 값으로 설정합니다.

    8. attributesnew_web_printer_attributes로 설정합니다.

    9. promisenew_web_printer_attributesresolve합니다.

  3. promise를 반환합니다.

submitPrintJob() 메서드 단계는 다음과 같습니다.
  1. promise새 promise로 둡니다.

  2. 다음 단계를 병렬로 실행합니다.

    1. 프린터와 통신하는 동안 문제가 있는 경우, promise를 새 NetworkError DOMException으로 reject하고 이 단계를 중단합니다.

    2. fetchAttributes()의 알고리즘을 사용하여 attributes를 업데이트합니다.

    3. printersubmitPrintJob()가 실행되는 WebPrinter 인스턴스로 둡니다.

    4. template_attributes의 각 template_attribute에 대해 반복합니다.

    5. template_attribute가 해당 printerattributes에 대해 확인한 지원 값(예: mediaSourcemediaSourceSupported에 대해 확인한 값)을 포함하지 않는 경우, promise를 새 DataError DOMException으로 reject하고 이 단계를 중단합니다.

    6. pdf_data가 PDF 문서 데이터를 보유하도록 합니다. document_data Blob을 PDF 문서로 변환하고 그 값을 pdf_data로 설정합니다. document_data가 잘못된 형식, 즉 유효한 PDF 문서가 아닌 경우, promise를 새 DataError DOMException으로 reject하고 이 단계를 중단합니다.

    7. pdf_dataWebPrintJobTemplateAttributes와 함께 보내고 프린터에 인쇄 작업으로 제출합니다.

    8. print_jobWebPrintJob 인터페이스의 인스턴스로 둡니다. print_job을 방금 프린터에 제출한 인쇄 작업과 연결합니다.

  3. promiseprint_job으로 resolve합니다.

  4. promise를 반환합니다.

signalAbortSignal 타입이며, 인쇄 작업을 cancel()하는 데에도 사용할 수 있습니다.

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의 일부로 전달됩니다.

onjobstatechangeonjobstatechange 이벤트 타입에 대한 이벤트 핸들러 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 객체는 핑거프린팅에 사용될 수 있는 printerNameprinterId attributes를 노출합니다.

8.1.2. 인쇄 작업 위조

악성 코드 주입은 다음으로 이어질 수 있습니다.

이는 격리된 컨텍스트에서는 절대 발생해서는 안 됩니다.

8.1.3. 감시

애플리케이션은 프린터가 언제 사용 중인지 잠재적으로 관찰할 수 있습니다.

8.2. 완화 요소

IDL은 이 API가 격리된 컨텍스트에서만 노출되도록 요구합니다.

8.2.1. Permissions Policy

이 명세는 문자열 "web-printing"으로 식별되는 정책 제어 기능을 정의합니다. 그 기본 허용 목록"self"입니다.

documentpermissions policy는 해당 문서의 모든 콘텐츠가 getPrinters()를 사용할 수 있는지 여부를 결정합니다. 어떤 문서에서든 비활성화된 경우, 해당 문서의 어떤 콘텐츠도 getPrinters()사용하도록 허용되지 않습니다.

프린터에 대한 접근은 강력한 기능입니다. 사용자 에이전트는 명시적 권한 없이 웹 애플리케이션이 WebPrinter 객체에 접근할 수 있도록 허용해서는 안 됩니다.

사용자 동의는 특정 origin에 대해 얻어야 합니다. 동의 요청은 getPrinters() 메서드 호출에 의해 트리거되어야 합니다. 사용자 에이전트는 어떤 origin이 접근을 요청하는지 명확히 나타내고 사용자가 충분한 정보를 바탕으로 결정을 내릴 수 있도록 충분한 정보를 제공하는 권한 프롬프트를 표시해야 합니다.

사용자 에이전트는 임시 (예: "이 세션에서만") 권한과 영구 권한 모두에 대한 옵션을 제공해야 합니다. 사용자가 영구 접근을 허용했다는 사실을 잊어버릴 위험을 완화하기 위해, 임시 권한이 기본값이자 더 눈에 띄는 옵션이어야 합니다.

사용자에게는 이 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 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. RFC에서 요구 수준을 나타내기 위한 핵심 단어. 1997년 3월. 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"
};