기능 위임

커뮤니티 그룹 보고서 초안,

이 버전:
https://wicg.github.io/capability-delegation/spec.html
이슈 추적:
GitHub
편집자:
(Google Canada)

초록

제한된 API를 사용할 수 있는 능력을 다른 창으로 이전한다.

이 문서의 상태

이 명세는 Web Platform Incubator Community Group이 공개했다. 이는 W3C 표준이 아니며 W3C 표준화 트랙에 있지도 않다. W3C Community Contributor License Agreement (CLA)에 따라 제한적 옵트아웃 및 기타 조건이 적용됨에 유의하라. W3C Community and Business Groups에 대해 더 알아보라.

1. 소개

이 절은 비규범적이다.

이 명세는 스크립트가 제한된 API를 호출할 수 있는 자신의 능력을 자신이 신뢰하는 다른 브라우징 문맥에 위임할 수 있는 메커니즘을 정의한다. 여기서 초점은 위임된 기능을 시간 제약 방식으로 대상 브라우징 문맥에 노출하는 동적 위임 메커니즘이다.

1.1. 기능 위임이란 무엇인가?

웹의 많은 기능은 JS에서 제한된 방식으로 사용할 수 있다. 예를 들어:

기능 위임이란 어떤 프레임이 제한된 API를 호출할 수 있는 자신의 능력을 동적으로 포기하고, 신뢰할 수 있는 다른 (하위)프레임에 그 능력을 이전할 수 있게 하는 것을 의미한다. 여기서 "동적"이라는 말은 위임의 효과가 위임되는 기능에 의해 정의된 제한된 시간 동안만 지속된다는 뜻이다. 이는 브라우징 문맥에 기능을 정적으로(로드 시점에) 노출하는 것, 즉 iframe allow 속성을 통해 기능이 하위 프레임에 시간 제약 없이 노출되는 것과는 다르다.

1.2. 위임 시작과 기능 사용

기능 위임이 효과를 가지려면 두 개의 구별되는 단계가 필요하다. 첫 번째 단계는 "시작"으로, 하나의 브라우징 문맥이 다른 브라우징 문맥에 특정 기능이 위임되었음을 알리는 것이다. 시작 이후, 두 번째(즉 수신자) 브라우징 문맥은 위임된 기능을 "사용"하게 되며, 이는 일반적으로 기능이 정의한 메서드를 호출하는 것을 의미한다. 여기의 기능 위임 명세는 두 번째 단계에서 사용되는 API 인터페이스를 정의하지 않지만, API의 내부 동작은 재정의한다.

이 때문에 이 명세는 두 개의 구별되는 부분으로 구성된다. 즉 시작 단계를 위한 API를 정의하는 부분과, 하나의 특정 "사용자" API에 대한 위임 동작을 정의하는 부분이다. 두 번째 부분에서 이 명세는 Payment Request API에 필요한 동작 변경에 초점을 맞추며, 이는 앞으로 기능 위임을 활용할 다른 API에서의 유사한 변경을 위한 지침 역할을 하게 된다.

1.3. 일시적 가용성

위에서 언급한 두 단계는 모두 본질적으로 시간 제약을 가진다:

  1. 시작 단계는 활성화 소비 단계이므로, 이 단계는 최근 사용자 활성화 이후에만 허용된다. 또한 여기서 사용자 활성화를 소비하면 위임 메커니즘을 사용자 활성화당 한 번 이상 사용할 수 없다는 것이 보장된다. 이는 위임된 API에 대한 사용자 활성화 제한을 사실상 우회하기 위해 여러 프레임에 반복적으로 위임을 시도하는 것과 같은 기능 위임의 악의적 사용을 방지한다.

  2. 시작 단계가 성공적으로 완료된 뒤, 위임된 API는 대상 브라우징 문맥에서 몇 초 동안만 사용할 수 있게 된다. 여기서 정확한 시간 제한은 위임된 API가 자신의 명세에서 위임 동작을 어떻게 정의하는지에 따라 달라진다. 자체 시간 제한을 정의하지 않는 API의 경우, 기본 제한은 사용자 활성화 만료와 동일하다.

2. 예제

어떤 사이트가 마우스 클릭 후 하위 프레임에서 [payment-request] show()를 호출할 수 있는 기능을 위임하려는 경우, 위임할 기능을 지정하는 추가 옵션과 함께 하위 프레임에 메시지를 게시한다:
window.onclick = () => {
  targetWindow.postMessage('a_message', {delegate: "payment"});
};

메시지를 수신하면, 해당 하위 프레임은 사용자 활성화를 받지 않았더라도 show()를 사용할 수 있다:

window.onmessage = () => {
  const payRequest = new PaymentRequest(...);
  const payResponse = await payRequest.show();
  ...
}

3. 기능 위임 시작

브라우징 문맥이 기능을 다른 브라우징 문맥에 위임하려는 경우, 해당 기능을 지정하는 delegate라는 추가 WindowPostMessageOptions와 함께 두 번째 브라우징 문맥에 메시지를 게시한다. 이 옵션의 값은 feature-identifier여야 한다. 이 옵션은 그 값이 사용자 에이전트가 지원하는 어떤 features에도 해당하지 않으면 무시되어야 한다.

가능한 feature-identifier 값 목록은 여기에 있다.

3.1. HTML 명세에 대한 몽키 패치

WindowPostMessageOptions IDL 정의는 다음과 같은 추가 필드를 포함하게 된다:

DOMString? delegate;

window post message 알고리즘에서, 다음 단계:

  1. Let transfer be options["transfer"].

뒤에는 다음 두 개의 추가 단계가 이어진다:

  1. delegateoptions["delegate"]라고 하자.

  2. delegate가 null이 아니면:

    1. 사용자 에이전트가 delegate가 나타내는 feature의 위임을 지원하지 않으면, "NotSupportedError" DOMException을 던진다.

    2. targetWindowassociated Documentdelegate가 나타내는 feature를 allowed-to-use 할 수 없으면, "NotAllowedError" DOMException을 던진다.

    3. targetOrigin이 단일 U+002A ASTERISK 문자(*)이면, "NotAllowedError" DOMException을 던진다.

      targetOrigin의 기본값은 "/"이며, 메시지를 same-origin 대상으로 제한한다. "*"가 아닌 문자열을 사용해야 한다는 추가 요구사항은 cross-origin 메시지가 의도된 특정 오리진을 지정해야 함을 의미한다.
    4. sourceincumbentSettings전역 객체라고 하자.

    5. source일시적 활성화를 가지고 있지 않으면, "NotAllowedError" DOMException을 던진다.

    6. source에서 사용자 활성화를 소비한다.

4. 위임된 기능 추적

브라우징 문맥에 위임된 기능은 Window.DELEGATED_CAPABILITY_TIMESTAMPS라는 이름의 맵을 사용하여 추적된다. 어떤 기능이 Window에 위임될 때마다, 기능을 나타내는 feature-identifier와 같은 키와, 현재 DOMHighResTimeStamp와 같은 값을 가진 항목이 DELEGATED_CAPABILITY_TIMESTAMPS에 추가된다. 맵에 이미 같은 키에 대한 항목이 있으면, 기존 값은 현재 DOMHighResTimeStamp로 갱신된다.

4.1. HTML 명세에 대한 몽키 패치

window post message 알고리즘 바로 앞에, 다음과 같은 새 문단이 삽입된다:

브라우징 문맥에 위임된 기능을 추적하기 위해, 각 Window을 가지며, 이는 feature-identifier에서 DOMHighResTimeStamp로 가는 DELEGATED_CAPABILITY_TIMESTAMPS라고 불린다. 이 맵은 빈 맵으로 초기화된다.

window post message 알고리즘에서, 현재 Step 8에 두 개의 추가 하위 단계가 추가된다. 첫 번째 추가 하위 단계는 다음 하위 단계 뒤에 삽입된다:

  1. Queue a global task ...

    1. Let origin be the serialization of incumbentSettings’s origin.

다음과 같다:

  1. Queue a global task ... (변경 없음)

    1. delegateoptions["delegate"]라고 하자.

두 번째 추가 하위 단계는 다음 하위 단계 뒤에 삽입된다:

  1. Queue a global task ...

    1. Let newPorts be a new frozen array consisting of ...

다음과 같다:

  1. Queue a global task ... (변경 없음)

    1. Let newPorts be a new frozen array consisting of ... (번호 매김을 제외하고 변경 없음)

    2. delegate가 null이 아니고, 사용자 에이전트가 delegate 위임을 지원하면, DELEGATED_CAPABILITY_TIMESTAMPS[delegate]를 현재 고해상도 시간으로 설정한다.

5. 위임된 기능 동작 정의

위임된 동작을 정의하는 모든 기능은 해당 기능에 적절한 방식으로 Window.DELEGATED_CAPABILITY_TIMESTAMPS의 해당 항목을 사용한다. 아래는 하나의 특정 기능에 필요한 명세 변경이다.

5.1. Payment Request 명세에 대한 몽키 패치

show() 알고리즘에서, 위임된 동작을 구현하기 위해 다음 단계들이 대체된다:

두 단계:

  1. If the relevant global object of request does not have transient activation:

    1. Return a promise rejected with a "SecurityError" DOMException.

  2. Consume user activation of the relevant global object.

는 다음 세 단계로 대체된다:

  1. request의 관련 전역 객체가 일시적 활성화를 가지고 있지 않고, 관련 전역 객체의 DELEGATED_CAPABILITY_TIMESTAMPS["payment"] 타임스탬프가 undefined이거나 만료된 경우:

    1. "SecurityError" DOMException으로 거부된 promise를 반환한다.

  2. request의 관련 전역 객체가 일시적 활성화를 가지고 있지 않으면, 맵 항목 DELEGATED_CAPABILITY_TIMESTAMPS["payment"]를 지운다.

  3. 그렇지 않으면, 관련 전역 객체의 사용자 활성화를 소비한다.

5.2. Fullscreen 명세에 대한 몽키 패치

requestFullscreen() 알고리즘에서, 위임된 동작을 구현하기 위해 다음 변경이 수행된다:

Step 5의 마지막 조건:

  1. If any of the following conditions are false, then set error to true: ...

    • This’s relevant global object has transient activation or the algorithm is triggered by a user generated orientation change.

은 다음으로 대체된다:

  1. If any of the following conditions are false, then set error to true: ... (변경 없음)

    • this의 관련 전역 객체가 일시적 활성화를 가지고 있거나, this의 관련 전역 객체에 있는 DELEGATED_CAPABILITY_TIMESTAMPS["fullscreen"] 타임스탬프가 undefined가 아니며 만료되지 않았거나, 또는 알고리즘이 사용자 생성 orientation change에 의해 트리거된 경우.

Step 10 바로 앞:

  1. Let fullscreenElements be an ordered set initially consisting of this.

에 다음 새 단계가 삽입된다:

  1. this의 관련 전역 객체가 일시적 활성화를 가지고 있지 않으면, this의 관련 전역 객체에서 맵 항목 DELEGATED_CAPABILITY_TIMESTAMPS["fullscreen"]를 지운다.

  2. Let fullscreenElements be an ordered set initially consisting of this. (번호 매김을 제외하고 변경 없음)

5.3. [SCREEN-CAPTURE] 명세에 대한 몽키 패치

getDisplayMedia() 알고리즘에서, 위임된 동작을 구현하기 위해 다음 변경이 수행된다:

Step 3의 조건:

  1. If the relevant global object of this does not have transient activation, return a promise rejected with a DOMException object whose name attribute has the value InvalidStateError.

은 다음으로 대체된다:

  1. this의 관련 전역 객체일시적 활성화를 가지고 있지 않고, this의 관련 전역 객체에 있는 DELEGATED_CAPABILITY_TIMESTAMPS["display-capture"] 타임스탬프가 undefined이거나 만료된 경우, name 속성 값이 InvalidStateErrorDOMException 객체로 거부된 promise를 반환한다.

적합성

문서 규약

적합성 요구사항은 설명적 단언과 RFC 2119 용어의 조합으로 표현된다. 이 문서의 규범적 부분에서 쓰인 핵심어 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, 그리고 “OPTIONAL”은 RFC 2119에 설명된 대로 해석되어야 한다. 다만 가독성을 위해, 이 명세에서는 이러한 단어들이 모두 대문자로 나타나지는 않는다.

이 명세의 모든 텍스트는 명시적으로 비규범적이라고 표시된 절, 예제 및 참고를 제외하고 규범적이다. [RFC2119]

이 명세의 예제는 “예를 들어”라는 말로 도입되거나 규범적 텍스트와 분리되어 class="example"으로 표시된다. 다음과 같다:

이는 정보성 예제의 예이다.

정보성 참고는 “참고”라는 단어로 시작하며 규범적 텍스트와 분리되어 class="note"로 표시된다. 다음과 같다:

참고, 이는 정보성 참고이다.

적합 알고리즘

알고리즘의 일부로 명령형으로 표현된 요구사항 (예: "모든 선행 공백 문자를 제거한다" 또는 "false를 반환하고 이 단계를 중단한다")은 알고리즘을 도입할 때 사용된 핵심어 ("must", "should", "may" 등)의 의미로 해석되어야 한다.

알고리즘이나 특정 단계로 표현된 적합성 요구사항은 최종 결과가 동등하기만 하다면, 어떤 방식으로든 구현될 수 있다. 특히 이 명세에 정의된 알고리즘은 이해하기 쉽도록 의도되었으며, 성능이 뛰어나도록 의도된 것은 아니다. 구현자는 최적화할 것을 권장한다.

색인

이 명세에서 정의된 용어

참조로 정의된 용어

참고 문헌

규범적 참고 문헌

[FULLSCREEN]
Philip Jägenstedt. Fullscreen API Standard. Living Standard. URL: https://fullscreen.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[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/
[PAYMENT-REQUEST-1.1]
Marcos Caceres; Rouslan Solomakhin; Ian Jacobs. Payment Request API 1.1. URL: https://w3c.github.io/payment-request/
[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. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SCREEN-CAPTURE]
Jan-Ivar Bruaroey; Elad Alon. Screen Capture. URL: https://w3c.github.io/mediacapture-screen-share/
[WebCryptoAPI]
Mark Watson. Web Cryptography API. URL: https://w3c.github.io/webcrypto/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

정보성 참고 문헌

[PAYMENT-REQUEST]
Marcos Caceres; Rouslan Solomakhin; Ian Jacobs. Payment Request API. URL: https://w3c.github.io/payment-request/