1. 소개
이 섹션은 규범적이지 않습니다.
이 명세서는 시스템 클립보드가 웹 애플리케이션에 어떻게 노출되는지 정의합니다.
이 명세서에는 두 가지 일반적인 API가 설명되어 있습니다:
-
클립보드 이벤트 API - 이 API는 잘라내기, 복사, 붙여넣기와 같은 일반적인 클립보드 작업에 연결하여 웹 애플리케이션이 필요에 따라 클립보드 데이터를 조정할 수 있는 방법을 제공합니다.
-
비동기 클립보드 API - 이 API는 클립보드 데이터를 직접 읽고 쓸 수 있는 접근을 제공합니다. 이는 강력한 기능으로 간주되기 때문에, 이 API에 대한 접근은 권한에 의해 제어됩니다.
2. 사용 사례
이 섹션은 규범적이지 않습니다.
2.1. 기본 클립보드 동작 변경
기본 클립보드 작업(잘라내기/복사/붙여넣기)을 변경하고 싶은 다양한 시나리오가 있습니다. 몇 가지 예시를 들면 다음과 같습니다:
- 메타데이터 문서 저장소에서 텍스트를 복사할 때, 복사된 텍스트에 원본 콘텐츠에 대한 메타데이터를 포함시키는 것이 유용할 수 있습니다.
- 서식 있는 콘텐츠 편집 하이퍼링크나 기타 구조를 포함한 텍스트를 복사할 때, 중요한 정보를 보존하기 위해 콘텐츠를 다시 포맷하는 기능이 종종 필요합니다.
- 내장 의미를 가진 그래픽 웹 애플리케이션에서 서식 있는 텍스트 또는 [SVG11]과 같은 그래픽 콘텐츠를 조작할 수 있도록, 렌더링된 콘텐츠만 복사하는 것이 아니라 더 많은 정보를 복사할 수 있는 메커니즘을 제공하는 것이 유용합니다.
- 수학적 정보 수학과 같은 콘텐츠의 경우, 단순히 렌더링된 텍스트를 복사하여 다른 애플리케이션에 붙여넣으면 대부분의 의미가 손실됩니다. 예를 들어 MathML을 평문 텍스트로 복사할 때는 "^" 기호로 거듭제곱을 표시하는 등 변환이 필요합니다. XML 소스를 클립보드에 넣고, 붙여넣기 시점에 적절한 변환이 이루어질 수도 있습니다.
2.2. 원격 클립보드 동기화
원격 기기와 통신하는 웹 애플리케이션(예: 원격 액세스 또는 원격 셸 애플리케이션)에서는 클립보드 데이터가 두 기기 간에 동기화되어야 할 필요가 자주 있습니다.
이 사용 사례에서 중요한 점은 사용자 제스처나 상호작용 없이도 클립보드에 접근해야 한다는 것입니다.
write()
메서드를 통해 로컬 클립보드에 데이터를 씁니다. clipboardchange
이벤트를 감지하고, 클립보드가 업데이트될 때마다 read()
메서드로 클립보드에서 새로운 데이터를 읽은 후, 그 데이터를 원격 기기로 전송합니다. 2.3. 클립보드 작업 트리거
사용자 에이전트에 대체 인터페이스를 제공하는 애플리케이션은 때때로 사용자 에이전트에서 클립보드 작업을 트리거할 필요가 있습니다.
예를 들어, 보다 접근성 높은 인터페이스를 제공하는 화면 판독기 애플리케이션을 생각해 볼 수 있습니다. 이 판독기는 콘텐츠를 표시하고 사용자가 상호작용할 수 있도록 하지만, 클립보드 복사와 같은 작업은 브라우저에서 수행되어야 클립보드 콘텐츠가 올바르게(브라우저가 복사 시 추가하는 메타데이터 포함) 설정됩니다.
3. 용어 정리
editable context는 editing host이거나 textarea 요소, 또는 type 속성이 "text", "search", "tel", "url", "email", "password", "number" 중 하나로 설정된 input 요소를 의미합니다.
4. 모델
플랫폼은 시스템 클립보드를 제공합니다.
시스템 클립보드는 여러 시스템 클립보드 아이템의 목록을 가지고 있으며, 이들은 총칭해서 시스템 클립보드 데이터라 부릅니다.
각 시스템 클립보드 아이템은 여러 시스템 클립보드 표현의 목록을 가집니다.
각 시스템 클립보드 표현은 문자열인 name과 바이트 시퀀스인 data를 가집니다.
5. 클립보드 이벤트
5.1. 클립보드 이벤트 인터페이스
ClipboardEvent 인터페이스는 Event
인터페이스를 확장합니다.
dictionary :ClipboardEventInit EventInit {DataTransfer ?=clipboardData null ; };
- clipboardData
-
이 이벤트와 관련된 데이터 및 메타데이터를 저장하는
DataTransfer객체입니다.
[Exposed =Window ]interface :ClipboardEvent Event {(constructor DOMString ,type optional ClipboardEventInit = {});eventInitDict readonly attribute DataTransfer ?; };clipboardData
- clipboardData
-
clipboardData 속성은
DataTransfer인터페이스의 인스턴스로, 스크립트가 사용자가 복사, 잘라내기, 붙여넣기 작업을 할 때 시스템 클립보드의 값을 읽고 조작할 수 있도록 합니다. 관련 drag data store는 시스템 클립보드의 필터링된 실시간 뷰로, 구현체가 스크립트가 안전하게 접근할 수 있다고 아는 필수 데이터 타입만 노출합니다. 합성 이벤트에서는 drag data store에 이벤트를 생성한 스크립트가 추가한 데이터만 포함됩니다.clipboardData 객체의
items및files속성을 통해 클립보드에서 다중 파트 혹은 비텍스트 데이터를 처리할 수 있습니다.
이 인터페이스는 이벤트를 생성하는 데 사용할 수 있습니다. 아래는 예시입니다:
var pasteEvent = new ClipboardEvent('paste');
pasteEvent.clipboardData.items.add('My string', 'text/plain');
document.dispatchEvent(pasteEvent);
참고: 합성 클립보드 이벤트는 실제로 클립보드나 문서를 변경하지 않습니다. 즉, 위의 스크립트는 paste 이벤트를 발생시키지만, 데이터가 문서에 붙여넣어지지는 않습니다.
5.2. 클립보드 이벤트
5.2.1.
clipboardchange 이벤트
clipboardchange
이벤트는 시스템 클립보드의 내용이 변경될
때마다 발생합니다. 이러한 변경은 다음과 같은 원인(포괄적이지 않음)일 수 있습니다:
-
사용자가 직접 잘라내기나 복사 작업을 수행
-
스크립트가 § 7 비동기 클립보드 API를 사용하여 클립보드에 쓰기
-
사용자 에이전트 외부에서 클립보드가 갱신되는 작업
5.2.1.1. clipboardchange 이벤트 발생 단계
Document
document에 대해 clipboardchange 이벤트를 발생시키려면:
-
document에 지속적 활성화가 없고 document에 클립보드에서 읽기 권한이 없다면, 반환합니다.
-
global을 document의 관련 글로벌 객체로 둡니다.
-
document에 시스템 포커스가 있는 경우:
-
changeId를 document를 인자로 하여 changeId 생성을 실행한 결과로 둡니다.
-
eventInit를 새
ClipboardChangeEventInit딕셔너리로 두고,types멤버는 types로,changeId멤버는 changeId로 설정합니다. -
ClipboardChangeEvent와 eventInit을 사용하여, global에서clipboardchange라는 이름의 이벤트를 발생시킵니다.
-
document에 시스템 포커스가 없는 경우:
-
document의 clipboardchange 보류 플래그를 true로 설정합니다.
-
사용자 에이전트는 이벤트가 전달되기 전에 새 변경 사항에 의해 대체된 클립보드 변경에 대해
clipboardchange
이벤트 발생을 건너뛸 수 있습니다(MAY).
이 최적화는 클립보드가 빠르게 연속 변경되는 상황에서 성능을 높일 수 있습니다. 왜냐하면 오래된 변경 알림을 전달하는 것은 웹 애플리케이션에 가치 없이 처리 리소스만 소모하기 때문입니다.
5.2.1.2. 문서 포커스 단계
Document
document가 시스템 포커스를 얻을 때:
-
document의 clipboardchange 보류 플래그가 true이면:
-
document의 clipboardchange 보류 플래그를 false로 설정한다.
-
changeId를 document를 인자로 하여 changeId 생성을 실행한 결과로 둔다.
-
eventInit을 새
ClipboardChangeEventInit딕셔너리로 두고,types멤버는 types로,changeId멤버는 changeId로 설정한다. -
global을 document의 관련 글로벌 객체로 둔다.
-
eventInit을 사용하여, global에서
clipboardchange라는 이름의 이벤트를ClipboardChangeEvent로 발생시킨다.
-
중첩된 브라우징 컨텍스트의 문서의 경우, clipboardchange
이벤트는 각 Document
에서 자신의 포커스 상태에 따라 독립적으로 발생합니다. 클립보드 변경은 시스템 포커스가 있는 단일 문서(그 문서에 지속적 활성화 또는 영구적인 클립보드 권한이 있는 경우)에 대해 이벤트를 발생시킵니다.
참고: clipboardchange 이벤트는 지속적
활성화 이후에만 사용할 수 있으며, 문서에 클립보드에서 읽기 위한 영구 권한이 없는 한 그렇습니다. 영구 클립보드 권한을 지원하는 사용자 에이전트에서는, 해당 권한이 있는 사이트가
sticky activation 없이도 clipboardchange 이벤트를 받을 수 있습니다. 왜냐하면 그 권한이 이미 더 민감한 클립보드 데이터에 접근 권한을 부여하기
때문입니다.
changeId
는 각 클립보드 변경 작업에 대한 고유 식별자를 제공합니다. 동일한 클립보드 변경에 대해 동일한 storage key를 가진 모든 창과
탭은 동일한 changeId
값을 가진 이벤트를 받으므로, 여러 창이 있을 때도 한 번만 이벤트를 처리하도록 중복 처리가 가능합니다.
이 식별자는 storage key에 한정되며 교차 storage key 상관 기능은
제공하지 않습니다.
clipboardchange
이벤트는 버블링되지 않으며 취소도 불가능합니다.
이 이벤트는 사용자 동작이 아니라 시스템
클립보드의 상태 변화에 의해 트리거되기 때문입니다.
dictionary :ClipboardChangeEventInit EventInit {sequence <DOMString >= [];types bigint = 0; };changeId
[Exposed =Window ]interface :ClipboardChangeEvent Event {(constructor DOMString ,type optional ClipboardChangeEventInit = {});eventInitDict readonly attribute FrozenArray <DOMString >;types readonly attribute bigint ; };changeId
- types
-
이 이벤트가 발생할 때 시스템 클립보드에 사용 가능한 필수 데이터 유형을 나타내는
FrozenArrayDOMString객체를 반환합니다. 옵션 데이터 유형과 커스텀 포맷은 지문 수집 표면을 줄이기 위해 제외됩니다. - changeId
-
이 특정 클립보드 변경 작업에 대한 고유 식별자를 나타내는
bigint를 반환합니다. 이 식별자는 동일한 storage key를 가진 모든 창과 탭에서 동일한 클립보드 변경에 대해 일치하므로, 여러 창에서 동일한 클립보드 변경 알림이 발생할 때 이벤트를 중복 처리하지 않도록 할 수 있습니다.changeId는 암호학적으로 파생된 128비트 정수입니다. 클립보드에 무언가를 쓴 후에는changeId값이 쓰기 전과 다른 값이 나올 것이라는 보장만 있습니다.
5.2.1.4. ChangeId 생성
Document
document에 대해 changeId 생성은 다음 단계를 따릅니다:
-
globalChangeId를 현재 시스템 클립보드 상태를 나타내는 사용자 에이전트 고유 식별자로 둡니다. 이 값은 시스템 클립보드가 변경될 때마다 바뀌며, 사용자 에이전트가 재시작되면 초기화됩니다.
-
storageKey를 document의 비스토리지 목적의 스토리지 키 얻기 실행 결과로 둡니다.
-
storageKeyBytes를 storageKey의 사용자 에이전트 고유 이진 표현으로 둡니다.
-
hashedValue를 globalChangeId(바이트)와 storageKeyBytes를 이어붙인 값에 대해 암호화 해시 함수(예: SHA-256)를 적용한 결과로 둡니다.
-
hashedValue에서 파생된 128비트 정수를 반환합니다(예: 해시 출력의 처음 128비트).
위 알고리즘은 동일한 출처, 동일 파티셔닝인 문서에 대해 동일한 클립보드 변경에는 동일한 change ID를 반환해 여러 창/탭에서의 이벤트 중복을 예방합니다. 파티션 간 추적에 사용될 수 있는 교차 파티션 상관 기능은 불가능하며, 클라이언트 측 저장소 파티셔닝 변경이 도입될 때도 자동 익명성을 제공합니다.
changeId
는 브라우저 재시작 시 유지되지 않습니다. 왜냐하면 globalChangeId 카운터가 재시작 시 초기화되기 때문입니다. 마찬가지로 사이트 데이터를 지우면, 해당 탭은
새로고침되어야 하고, 새 이벤트 리스너는 앞으로 발생하는 새로운 changeId에 대한 이벤트만 받습니다.
합성 cut
및 copy
이벤트는 시스템 클립보드를 변경하지
않으므로,
"clipboardchange" 이벤트를 트리거하지 않습니다.
clipboardchange
이벤트를 사용하면 웹 애플리케이션이 효율적으로
클립보드 변경을 감지해, 사용 가능한 데이터 포맷에 따라 동적으로 UI를 업데이트할 수 있습니다:
// 다중 창 앱은 처리된 changeId를 추적해 중복을 피합니다.
const processedChangeIds = new Set();
// 클립보드 변경 이벤트 리스너 등록
navigator.clipboard.addEventListener('clipboardchange', (e) => {
// 여러 창에서 동일 changeId 중복 방지
if (processedChangeIds.has(e.changeId)) {
return; // 이미 처리한 변경입니다.
}
processedChangeIds.add(e.changeId);
// 클립보드의 데이터 유형 확인
const hasText = e.types.includes('text/plain');
const hasHTML = e.types.includes('text/html');
const hasImage = e.types.includes('image/png');
// 사용 가능한 포맷에 따라 UI 갱신
document.getElementById('paste-text-btn').disabled = !hasText;
document.getElementById('paste-html-btn').disabled = !hasHTML;
document.getElementById('paste-image-btn').disabled = !hasImage;
// 원격 데스크톱 앱은 changeId당 한 번만 동기화
if (hasText || hasHTML || hasImage) {
syncClipboardToRemote(e.changeId);
}
});
// 또는, onclipboardchange 속성을 사용할 수도 있습니다.
// navigator.clipboard.onclipboardchange = (e) => { ... };
이벤트 기반 방식은
read()
또는 readText()
로 폴링하는 것보다 효율적이며, 클립보드 접근에 사용자 활성화를 요구하는 브라우저에서도 동작합니다. UI가 타이머 대기 없이 클립보드 변경에 즉시 반응할 수 있기 때문입니다.
changeId
는 여러 창을 가진 앱에 특히 유용하며,
동일 storage key를 가진 모든 창에서 각 클립보드 변경을 한 번만 처리하도록 해줍니다.
5.2.2. copy
이벤트
사용자가 복사 작업을 시작하면, 사용자 에이전트는 클립보드 이벤트 copy를
발생시킵니다.
이 이벤트가 취소되지 않으면, 현재 선택된 데이터가 시스템 클립보드에 복사됩니다. 현재 문서의 선택 영역은 영향을 받지 않습니다.
copy
이벤트는 버블링되며, 취소 가능하고, composed입니다.
이 이벤트의 처리 모델에 대한 자세한 설명은 § 8.1 복사 동작을 참고하세요.
합성 copy
이벤트를 수동으로 생성하여 디스패치할 수 있지만,
시스템 클립보드의 내용에는 영향을 주지
않습니다.
5.2.3. cut
이벤트
사용자가 잘라내기 작업을 시작하면, 사용자 에이전트는 클립보드 이벤트 cut를
발생시킵니다.
editable context에서,
이벤트가 취소되지 않으면 선택된 데이터가 시스템
클립보드에 저장되고 문서에서 선택 영역이 제거됩니다.
cut
이벤트는 선택 영역이 제거되기 전에 발생합니다. 잘라내기 작업이 완료되면 선택이 접힙니다.
비-editable context에서는
clipboardData
가 빈 리스트입니다. 이 경우에도 cut
이벤트는 여전히 발생합니다.
cut
이벤트는 버블링되며, 취소 가능하고, composed입니다.
이 이벤트의 처리 모델에 대한 자세한 설명은 § 8.2 잘라내기 동작을 참고하세요.
합성 cut
이벤트를 수동으로 생성하여 디스패치할 수 있지만,
문서나 시스템 클립보드의 내용에는 영향을
주지 않습니다.
5.2.4.
paste
이벤트
사용자가 붙여넣기 작업을 시작하면, 사용자 에이전트는 클립보드 이벤트 paste를
발생시킵니다.
이 이벤트는 클립보드 데이터가 문서에 삽입되기 전에 발생합니다.
커서가 editable context에 있으면, 붙여넣기 동작은 해당 컨텍스트에서 지원하는 가장 적합한 포맷(있는 경우)으로 클립보드 데이터를 삽입합니다.
비-editable context에서는
붙여넣기 동작이 아무런 영향을 미치지 않지만,
paste
이벤트는 항상 발생합니다.
paste
이벤트는 버블링되며, 취소 가능하고, composed입니다.
이 이벤트의 처리 모델에 대한 자세한 설명은 § 8.3 붙여넣기 동작을 참고하세요.
합성 paste
이벤트를 수동으로 생성하여 디스패치할 수 있지만,
문서의 내용에는 영향을 주지 않습니다.
5.3. 다른 스크립트 및 이벤트와의 통합
5.3.1. 클립보드 수정을 허용하는 이벤트 핸들러
다음 조건 중 하나라도 true이면, 이벤트 핸들러는 클립보드에 쓸 수 있습니다:
-
이벤트를 트리거하는 동작이 사용자 에이전트의 자체 UI(예: "복사" 메뉴 항목이나 바로가기 키)에서 시작된 경우
-
이벤트를 트리거하는 동작이 팝업 표시가 허용된 스크립팅 스레드에서 시작된 경우
구현체는 해당 이벤트 타입이 사용자 의도를 반영한다고 판단될 경우, 다른 신뢰할 수 있는 이벤트 타입에도 클립보드 수정 권한을 허용할 수 있습니다. 또한 구현체가 특정 사이트나 앱에 원천 스레드와 무관하게 클립보드 수정을 신뢰하도록 구성할 수도 있습니다.
합성 cut
및 copy
이벤트는 시스템 클립보드의 데이터를 수정해서는 안 됩니다.
5.3.2. 클립보드 읽기를 허용하는 이벤트 핸들러
다음 조건 중 하나라도 true이면, 이벤트 핸들러는 시스템 클립보드에서 데이터를 읽을 수 있습니다:
-
이벤트를 트리거하는 동작이 사용자 에이전트의 자체 UI(예: "붙여넣기" 메뉴 항목이나 바로가기 키)에서 시작된 경우
-
동작을 트리거하는 스크립트가 구현체에 따라 클립보드 데이터를 읽을 권한을 부여받은 사이트에서 실행 중인 경우
-
동작을 트리거하는 이벤트가 클립보드 읽기 권한이 있는 앱에서 발생한 경우
합성 paste
이벤트는 스크립트에 실제 시스템 클립보드의 데이터 접근 권한을 주어서는 안 됩니다.
5.3.3. 서식 있는 텍스트 편집 API와의 통합
구현체가 스크립트를 통해 클립보드 명령을 실행하는 방법을 지원하는 경우, 예를 들어 document.execCommand() 메서드에 "cut", "copy",
"paste" 명령을 넘기는 방식이라면, 구현체는 반드시 해당 동작을 트리거하고, 그에 따라 관련 클립보드 이벤트를 디스패치해야 합니다.
스크립팅 API를 통해 복사, 잘라내기, 붙여넣기 동작을 트리거할 때 따라야 할 단계는 다음과 같습니다:
-
해당 동작을 동기적으로 실행합니다.
-
동작의 반환값을 API 호출의 반환값으로 사용합니다.
참고: 스크립팅 API를 통해 트리거된 복사 및 잘라내기 명령은 이벤트가 신뢰되고 사용자가 트리거한 경우 또는 구현체가 이를 허용하도록 설정된 경우에만 실제 클립보드 내용을 변경합니다. 붙여넣기 명령은 구현체가 허용하도록 설정된 경우에만 paste 이벤트를 발생시키고 클립보드 내용에 접근할 수 있습니다. 구현체가 클립보드 읽기 및 쓰기 접근을 허용하도록 구성하는 방법은 이 명세서의 범위에 포함되지 않습니다.
5.3.4. 다른 이벤트와의 상호작용
클립보드 작업이 키보드 입력에 의해 트리거된 경우, 구현체는 반드시 해당 클립보드 작업을 시작하는 이벤트를 발생시켜야 합니다. 이 이벤트는 비동기적이지만, 반드시 관련 키의 keyup 이벤트 전에 디스패치되어야 합니다.
잘라내기 및 붙여넣기 작업은 구현체가 지원하는 다른 이벤트(예: textInput, input, change, validation 이벤트, DOMCharacterDataModified, DOMNodeRemoved / DOMNodeInserted 등)를 발생시킬 수 있습니다. 이러한 이벤트는 cut/paste 이벤트 처리 후에 큐에 따라 발생합니다.
구현체는 복사 작업에 대해 textInput, input, change, validation과 같은 다른 입력 관련 이벤트를 발생시켜서는 안 됩니다.
5.3.5. 선택 영역이나 포커스를 수정하는 이벤트 리스너
이벤트 리스너가 선택 영역이나 포커스 가능한 영역을 수정한 경우, 클립보드 동작은 반드시 수정된 선택 영역에서 완료되어야 합니다.
6. 클립보드 이벤트 API
클립보드 이벤트 API를 사용하면 사용자 에이전트의 기본 잘라내기, 복사, 붙여넣기 동작을 오버라이드할 수 있습니다.
클립보드 접근은 표준 DataTransfer
메서드를 사용하여 items
를 변형합니다. 이 작업은 ClipboardEvent의
clipboardData
속성을 통해 이루어집니다.
이 API들은 ClipboardEvent
핸들러의 컨텍스트 내에서만 클립보드 데이터에 접근할 수 있습니다.
참고: 클립보드 이벤트 핸들러 외부에서 클립보드에 접근해야 한다면 § 7 비동기 클립보드 API를 참고하세요.
참고: 클립보드 이벤트 API는 동기적이므로, 할 수 있는 작업에 제한이 있습니다. 권한 요청이나 이미지 트랜스코딩 같은 잠재적으로 블로킹되는 동작은 지원하지 않습니다. 블로킹 또는 시간이 오래 걸리는 작업을 지원하는 더 강력한 API는 § 7 비동기 클립보드 API를 참고하세요.
6.1. 복사 이벤트 오버라이드
기본 copy
이벤트 동작을 오버라이드하려면 copy
이벤트 핸들러를 추가하고, 이 핸들러에서 preventDefault()
를 호출하여 이벤트를 취소해야 합니다.
이벤트를 취소해야만 시스템 클립보드가
clipboardData
의 데이터로 업데이트됩니다. ClipboardEvent
가 취소되지 않으면, 현재 문서 선택 영역의 데이터가 복사됩니다.
// 클립보드에 복사되는 내용을 덮어쓰는 예시
document.addEventListener('copy', function(e) {
// e.clipboardData는 처음에 비어 있지만, 복사하려는 데이터를 직접 설정할 수 있습니다.
e.clipboardData.setData('text/plain', 'Hello, world!');
e.clipboardData.setData('text/html', '<b>Hello, world!</b>');
// 현재 문서 선택 영역이 클립보드에 기록되는 것을 막기 위해 반드시 필요합니다.
e.preventDefault();
});
6.2. 잘라내기 이벤트 오버라이드
기본 cut
이벤트 동작을 오버라이드하려면 cut
이벤트 핸들러를 추가하고, 이 핸들러에서 preventDefault()
를 호출하여 이벤트를 취소해야 합니다.
이벤트를 취소해야만 시스템 클립보드가
clipboardData
의 데이터로 업데이트됩니다. ClipboardEvent
가 취소되지 않으면, 현재 문서 선택 영역의 데이터가 복사됩니다.
또한 cut
이벤트를 취소하면 문서가 갱신되지 않습니다(즉, 선택 영역이 제거되지 않습니다). 이벤트 핸들러에서 직접 선택된 텍스트를 문서에서 제거하는 작업을 해야 합니다.
// 클립보드에 복사되는 내용을 덮어쓰는 예시
document.addEventListener('cut', function(e) {
// e.clipboardData는 처음에 비어 있지만, 잘라내기 작업의 일부로 클립보드에 복사할 데이터를 직접 설정할 수 있습니다.
// 클립보드에 복사할 데이터를 직접 작성합니다.
e.clipboardData.setData('text/plain', 'Hello, world!');
e.clipboardData.setData('text/html', '<b>Hello, world!</b>');
// 잘라내기 작업을 취소할 것이므로, 선택된 텍스트를 직접 문서에서 제거해야 합니다.
deleteCurrentDocumentSelection();
// 현재 문서 선택 영역이 클립보드에 기록되는 것을 막기 위해 반드시 필요합니다.
e.preventDefault();
});
6.3. 붙여넣기 이벤트 오버라이드
기본 paste
이벤트 동작을 오버라이드하려면 paste
이벤트 핸들러를 추가하고, 이 핸들러에서 preventDefault()
를 호출하여 이벤트를 취소해야 합니다.
이벤트를 취소해야만 사용자 에이전트가 시스템 클립보드의 데이터로 문서를 갱신하지 않습니다.
또한 paste
이벤트를 취소하면 문서가 갱신되지 않습니다(즉, 아무것도 문서에 붙여넣어지지 않습니다). 이벤트 핸들러에서 직접 데이터를 문서에 붙여넣는 작업을 해야 합니다.
붙여넣기 시 drag data store mode 플래그가 읽기 전용이므로, setData()
를 paste
이벤트 핸들러에서 호출해도 삽입되는 데이터나 클립보드 데이터에는 영향을 주지 않습니다.
// 클립보드에 붙여넣는 내용을 덮어쓰는 예시
document.addEventListener('paste', function(e) {
// e.clipboardData에는 곧 붙여넣을 데이터가 들어 있습니다.
if (e.clipboardData.types.indexOf('text/html') > -1) {
var oldData = e.clipboardData.getData('text/html');
var newData = '<b>Ha Ha!</b> ' + oldData;
// 붙여넣기 작업을 취소할 것이므로, 직접 데이터를 문서에 붙여넣어야 합니다.
pasteClipboardData(newData);
// 기본 붙여넣기 동작을 막기 위해 반드시 필요합니다.
e.preventDefault();
}
});
6.4. 필수 데이터 타입
구현체는 아래 데이터 타입에 대해 운영체제의 기본 클립보드 포맷 설명을 인식해야 하며, DataTransferItemList
및 ClipboardItem
에서 붙여넣기 이벤트에 올바른 설명을 제공하고, 복사/잘라내기 이벤트에 대해 OS 클립보드에 올바른 데이터 포맷을 설정해야 합니다.
6.4.1. 클립보드에서 읽기
아래 데이터 타입은 클립보드에 해당하는 네이티브 타입이 있으면 붙여넣기 이벤트에서 노출되어야 합니다:
-
text/plain
-
text/html
-
image/png
6.4.2. 클립보드에 쓰기
아래 데이터 타입은 복사 및 잘라내기 이벤트에서 DataTransfer
객체에 추가될 때, 해당 네이티브 타입 설명과 함께 클립보드에 저장되어야 합니다.
-
text/plain
-
text/html
-
image/png
경고! 신뢰되지 않은 스크립트가 클립보드에 쓸 수 있는 데이터 타입은 보안 예방 차원에서 제한되어 있습니다. 신뢰되지 않은 스크립트가 클립보드에 로컬 소프트웨어의 보안 취약점을 유발하는 데이터를 넣으려 시도할 수 있습니다.
6.5. 선택적 데이터 타입
구현체는 아래 데이터 타입에 대해 운영체제의 기본 클립보드 포맷 설명을 인식할 수 있으며, ClipboardItem
에서 붙여넣기 이벤트에 올바른 설명을 제공하고, 복사/잘라내기 이벤트에 대해 OS 클립보드에 올바른 데이터 포맷을 설정할 수 있습니다.
아래 데이터 타입은 클립보드에 해당하는 네이티브 타입이 있으면 UA에서 노출할 수 있습니다:
-
text/uri-list
-
image/svg+xml
-
커스텀 포맷 "web "("web" 뒤에 U+0020 SPACE)로 시작하는 prefix와 suffix(끝부분에서 "web " 제거 후)가 MIME 타입 파싱 체크를 통과하는 경우
6.6. 비정제 데이터 타입
이 섹션은 규범적이지 않습니다.아래 데이터 타입은 UA가 반드시 정제(sanitize)하지 않아야 합니다:
-
image/png
아래 데이터 타입은 UA가 정제하지 않을 수도 있습니다:
선택적 비정제 데이터 타입은 웹 저자가 지정한 mime type 중 UA가 반드시 정제하지 않을 수도 있는 타입입니다. 선택적 비정제 데이터 타입의 유효 목록은 아래와 같습니다:
-
text/html
선택적 비정제 데이터 타입은 프라이버시 요구로 인해 UA에서 지원하지 않을 수 있습니다.
7. 비동기 클립보드 API
7.1. Navigator 인터페이스
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute Clipboard ; };clipboard
7.2. ClipboardItem 인터페이스
typedef Promise <(DOMString or Blob )>; [ClipboardItemData SecureContext ,Exposed =Window ]interface {ClipboardItem constructor (record <DOMString ,ClipboardItemData >,items optional ClipboardItemOptions = {});options readonly attribute PresentationStyle presentationStyle ;readonly attribute FrozenArray <DOMString >types ;Promise <Blob >getType (DOMString );type static boolean supports (DOMString ); };type enum {PresentationStyle ,"unspecified" ,"inline" };"attachment" dictionary {ClipboardItemOptions PresentationStyle = "unspecified"; };presentationStyle
clipboardItem = new ClipboardItem([items, options])-
새로운
ClipboardItem객체를 생성합니다. items는 표현 목록을 나타내며, 각 표현은 mime type과Promise(해당 mime type에 맞는Blob또는DOMString)를 가집니다. options는ClipboardItemOptions를 채우는 데 사용할 수 있습니다. 아래 예시 참고.const format1= 'text/plain' ; const promise_text_blob= Promise. resolve( new Blob([ 'hello' ], { type: format1})); const clipboardItemInput= new ClipboardItem( {[ format1] : promise_text_blob}, { presentationStyle: "unspecified" }); clipboardItem.getType(type)- mime type type에 해당하는
Promise(그Blob)를 반환합니다. clipboardItem.types- clipboard item 객체에 포함된 mime type 목록을 반환합니다.
ClipboardItem.supports(type)- type이 필수 데이터 타입 또는 선택적 데이터 타입에 있으면 true, 아니면 false를 반환합니다.
예를 들어, 사용자가 네이티브 앱의 스프레드시트에서 셀 범위를 복사하면 하나의 clipboard item이 생성됩니다. 사용자가 데스크톱에서 여러 파일을 복사하면, 그 파일 목록은 여러 clipboard item으로 표현됩니다.
일부 플랫폼은 클립보드에 한 번에 둘 이상의 clipboard item을 허용할 수 있고, 다른 플랫폼은 이전 clipboard item을 새 항목으로 대체합니다.클립보드 항목은 표현 목록을 가지고 있으며,
각각의 표현에는 연결된 mime 타입(MIME type), isCustom 플래그(처음엔 false)가 있으며, 이 표현이 시스템 클립보드의 잘 알려진 포맷이 아니라 웹 커스텀 포맷으로 취급되어야 하는지
나타냅니다. 그리고 data(ClipboardItemData)가
있습니다.
예시에서 사용자가 스프레드시트에서 셀 범위를 복사할 때, 이미지(image/png), HTML 테이블(text/html), 평문(text/plain), 웹 커스텀 포맷(web text/csv) 등 다양한 형태로 표현될 수 있습니다.
각 MIME 타입은 동일한 clipboard item의 다른 표현을 설명하며, 다양한 fidelity 수준에서 붙여넣기 대상 애플리케이션이 더 쉽게 활용할 수 있게 합니다.셀 범위를 이미지로 제공하면 사용자가 사진 편집 앱에 붙여넣을 수 있고, text/plain 포맷은 텍스트 편집 앱에서 사용할 수 있습니다.
clipboard item은 프레젠테이션 스타일 (PresentationStyle)을
가지고, 이는 붙여넣기하는 앱이 clipboard
item의 적절한 표현을 붙여넣기
위치에 인라인으로 삽입해야 할지, 첨부파일로 처리해야 할지 구분하는 데 도움을 줍니다.
단일 clipboard item만 지원하는 웹
앱은 첫 번째 clipboard item을
사용해야 합니다.
write()
는 마지막 clipboard item을
선택합니다.
ClipboardItem
객체에는 clipboard item이 연결되어 있으며, 이는 clipboard item입니다.
ClipboardItem
객체에는 types array가 연결되어 있으며, 이는 FrozenArray<DOMString>
ClipboardItem
객체 생성을 위해 clipboard
item clipboardItem과 Realm realm이 주어지면, 다음 단계를 실행합니다:
-
clipboardItemObject를 new
ClipboardItem로 realm과 함께 생성합니다. -
clipboardItemObject의 clipboard item을 clipboardItem으로 설정합니다.
new ClipboardItem(items, options)
생성자 단계:
-
items가 비어 있으면
TypeError를 던진다. -
options가 비어 있으면 options["presentationStyle"] = "unspecified"로 설정한다.
-
this의 clipboard item을 새로운 clipboard item으로 설정한다.
-
this의 clipboard item의 presentation style을 options["
presentationStyle"]로 설정한다. -
types를
DOMString의 리스트로 한다. -
items의 각 (key, value)에 대해:
-
representation을 새로운 representation으로 한다.
-
isCustom을 false로 한다.
-
key가 "web " prefix로 시작하면,
-
"web " prefix를 제거하고 남은 문자열을 key에 할당한다.
-
isCustom을 true로 설정한다.
-
-
representation의 isCustom 플래그를 isCustom으로 설정한다.
-
mimeType을 MIME 타입 파싱 결과(key 기준)로 한다.
-
mimeType이 실패이면
TypeError를 던진다. -
this의 clipboard item의 list of representations이 representation 중 MIME type이 mimeType이고 [representation/isCustom]이 isCustom인 항목을 포함하면
TypeError를 던진다.
위 단계는 사용자 에이전트가 잘 아는 mime-type과 저자가 커스텀 타입으로 다루길 원하는 타입 간의 충돌을 방지합니다. 예를 들어 저자의 items 목록에 "text/html" 과 "web text/html" 두 representation이 들어가는 것도 가능합니다.
-
representation의 MIME type을 mimeType으로 설정한다.
-
representation의 data를 value로 설정한다.
-
representation을 this의 clipboard item의 list of representations에 추가한다.
-
mimeTypeString을 MIME 타입 직렬화(mimeType 기준) 결과로 한다.
-
isCustom이 true이면 mimeTypeString 앞에 "web "을 붙인다.
-
mimeTypeString을 types에 추가한다.
-
-
this의 types array를 create a frozen array(types 기준) 결과로 설정한다.
7.2.1. presentationStyle
presentationStyle
getter의 단계는 this의
clipboard item의 presentation style을 반환하는 것이다.
7.2.2. types
types
getter의 단계는 this의
types
array를 반환하는 것이다.
7.2.3. getType(type)
이 메서드는 아래 단계를 실행해야 한다:
-
realm을 this의 relevant realm으로 한다.
-
isCustom을 false로 한다.
-
type이 "web " prefix로 시작하면:
-
"web " prefix를 제거하고 남은 문자열을 type에 할당한다.
-
isCustom을 true로 설정한다.
-
-
mimeType을 MIME 타입 파싱(type 기준) 결과로 한다.
-
mimeType이 실패이면
TypeError를 던진다. -
itemTypeList를 this의 clipboard item의 list of representations로 한다.
-
p를 새로운 promise(realm 기준)로 한다.
-
itemTypeList의 각 representation에 대해:
-
representation의 MIME type이 mimeType이고, representation의 isCustom이 isCustom이면:
-
representationDataPromise를 representation의 data로 한다.
-
representationDataPromise가 settle되면 반응:
-
representationDataPromise가 값 v로 fulfilled되면:
-
representationDataPromise가 reject되면:
-
p를 reject한다. 값은
"NotFoundError"DOMException(realm 기준).
-
-
-
p를 반환한다.
-
-
-
p를 reject한다. 값은
"NotFoundError"DOMException(realm 기준). -
p를 반환한다.
7.2.4. supports(type)
이 메서드는 아래 단계를 실행해야 한다:
-
type이 필수 데이터 타입 또는 선택적 데이터 타입에 포함되어 있으면 true를 반환한다.
-
그렇지 않으면 false를 반환한다.
7.3. Clipboard 인터페이스
typedef sequence <ClipboardItem >; [ClipboardItems SecureContext ,Exposed =Window ]interface :Clipboard EventTarget {Promise <ClipboardItems >read (optional ClipboardUnsanitizedFormats = {});formats Promise <DOMString >readText ();Promise <undefined >write (ClipboardItems );data Promise <undefined >writeText (DOMString ); };data dictionary {ClipboardUnsanitizedFormats sequence <DOMString >; };unsanitized
Clipboard
인터페이스의 일부 메서드는 여러 ClipboardItem
객체를 인자로 받거나 반환할 수 있습니다. 하지만, 모든 플랫폼이 하나 이상의 클립보드 항목을 지원하는 것은 아니며, 이런 플랫폼에서는 아래의 알고리즘에서 write()로
전달된 첫 번째 ClipboardItem
이외의 객체들은 무시되며, read()
와 readText()
는 OS에서 단 하나의 클립보드 항목만 가져옵니다.
clipboard items 객체는 시퀀스 형태의 클립보드 항목들의 집합입니다.
웹 작성자는 data라는 ClipboardItem
배열을 만들어야 시스템 클립보드에
write(data)
메서드를 사용해 콘텐츠를 쓸 수 있습니다.
read()
는 clipboard items 객체에 대한
Promise
를 반환하며, 이 객체는 시스템
클립보드 데이터의 내용을 나타냅니다.
unsanitized
는 시퀀스 형태의 DOMString
들로, 작성자가 옵션 비정제 데이터 타입으로 처리하길 원하는 mime type에 해당합니다.
unsanitized
옵션은 사용자 에이전트에서 지원하지 않을 수 있습니다. 웹 작성자는 unsanitized
에 명시한 MIME 타입의 콘텐츠가 실제로 비정제 상태로 반환된다고 가정해서는 안 됩니다. 이 옵션이 허용되지 않는 개인정보 보호 모드가 있을 수도 있기 때문입니다.
clipboard task source는 시스템 클립보드 데이터를 읽거나 쓸 때 실행됩니다.
7.3.1. read(formats)
read(formats)
메서드는 다음 단계를 실행해야 합니다:
-
p를 realm 안에서의 새 프라미스로 둡니다.
-
formats가 비어 있지 않으면:
-
formats["
unsanitized"]의 각 format에 대해:-
format이 옵션 비정제 데이터 타입에 없다면 p를 format
"NotAllowedError"DOMException으로 realm에서 reject 합니다.
-
-
-
다음 단계를 병렬로 실행합니다:
-
r을 클립보드 읽기 권한 확인을 실행한 결과로 둡니다.
-
r이 false이면:
-
글로벌 태스크 큐잉을 permission task source 위에서 realm의 글로벌 객체와 함께 p를
"NotAllowedError"DOMException으로 realm에서 reject 하게 합니다. -
이 단계를 중단합니다.
-
-
data를 시스템 클립보드 데이터의 복사본으로 둡니다.
-
data의 각 systemClipboardItem에 대해:
-
item을 새 클립보드 항목으로 둡니다.
-
systemClipboardItem의 각 systemClipboardRepresentation에 대해:
-
mimeType을 systemClipboardRepresentation의 name을 인자로 OS 특화 포맷에서 잘 알려진 mime type 얻기 알고리즘 실행 결과로 둡니다.
-
mimeType이 null이면, 이 반복을 건너뜁니다.
-
representation을 새 표현으로 둡니다.
-
representation의 MIME 타입을 mimeType으로 설정합니다.
-
isUnsanitized를 false로 둡니다.
-
formats가 비어 있지 않으면:
-
formats["
unsanitized"]의 각 format에 대해:-
format이 MIME 타입과 같으면, isUnsanitized를 true로 설정합니다.
-
-
-
representation의 data를 systemClipboardRepresentation의 data로 resolve 합니다.
저자는 getType을 호출한 뒤에도 시스템 클립보드에서 데이터를 비동기로 읽을 수 있어야 하지만, 이 단계 집합은 read 시점에 데이터가 제공됨을 암시합니다.
-
사용자 에이전트는 representation의 data를 정제(sanitize)할 수 있으나, representation의 MIME 타입의 essence가 "image/png"라면 메타데이터 보존을 위해 정제하지 않아야 하며, 아래 조건을 만족해도 정제하지 않아야 합니다:
-
representation의 MIME 타입이 옵션 비정제 데이터 타입 리스트에 포함된 경우.
-
isUnsanitized가 true인 경우.
-
-
representation을 item의 표현 목록에 추가합니다.
-
isUnsanitized를 false로 설정합니다.
-
-
item의 표현 목록 크기가 0보다 크면 item을 items에 추가합니다.
-
-
items의 크기가 0보다 크면:
-
firstItem을 items[0]로 둡니다.
-
firstItem에 대해 웹 커스텀 포맷 읽기 알고리즘을 실행합니다.
-
-
그렇지 않으면:
-
customItem을 새 클립보드 항목으로 둡니다.
-
customItem에 대해 웹 커스텀 포맷 읽기 알고리즘을 실행합니다.
-
customItem의 표현 목록 크기가 0보다 크면 customItem을 items에 추가합니다.
-
-
글로벌 태스크 큐잉을 clipboard task source 위에서 realm의 글로벌 객체와 함께 아래 단계를 실행하도록 합니다:
-
clipboardItems를 시퀀스<
ClipboardItem>로 둡니다. -
items의 각 클립보드 항목 underlyingItem에 대해:
-
clipboardItem을 underlyingItem, realm을 인자로 ClipboardItem 객체 생성 단계를 실행한 결과로 둡니다.
-
clipboardItem을 clipboardItems에 추가합니다.
-
-
p를 clipboardItems로 resolve합니다.
-
-
-
p를 반환합니다.
const items= await navigator. clipboard. read(); const textBlob= await items[ 0 ]. getType( "text/plain" ); const text= await ( new Response( textBlob)). text();
7.3.2. readText()
ThereadText()
메서드는 다음 단계를 실행해야 합니다:
-
p를 realm 내의 새 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
r을 클립보드 읽기 권한 확인 실행 결과로 둡니다.
-
r이 false이면:
-
글로벌 태스크 큐잉을 permission task source 위에서, realm의 글로벌 객체를 함께, p를
"NotAllowedError"DOMException으로 realm에서 reject 하게 합니다. -
이 단계를 중단합니다.
-
-
data를 시스템 클립보드 데이터의 복사본으로 둡니다.
일부 OS(예: Linux, "primary", "secondary", "selection")는 여러 개의 클립보드를 가집니다. 어떤 클립보드의 데이터를 읽을지 정의해야 합니다.
-
글로벌 태스크 큐잉을 clipboard task source 위에서, realm의 글로벌 객체를 함께, 아래 단계를 실행하도록 합니다:
-
data의 각 systemClipboardItem에 대해:
-
systemClipboardItem의 각 systemClipboardRepresentation에 대해:
-
mimeType을 systemClipboardRepresentation의 name을 인자로 OS 특화 포맷에서 잘 알려진 mime type 얻기 알고리즘 실행 결과로 둡니다.
-
mimeType이 null이면 이 반복을 계속합니다.
-
representation을 새 표현으로 둡니다.
-
representation의 MIME 타입의 essence가 "text/plain"이면:
-
representation의 MIME 타입을 mimeType으로 설정합니다.
-
representationDataPromise를 representation의 data로 둡니다.
-
React 하여 representationDataPromise가 완료될 때:
-
representationDataPromise가 값 v로 성공(fulfilled)된 경우:
-
representationDataPromise가 reject된 경우:
-
p를
"NotFoundError"DOMException과 함께 realm에서 Reject 합니다. -
p를 반환합니다.
-
-
-
-
-
-
p를
"NotFoundError"DOMException과 함께 realm에서 Reject 합니다. -
p를 반환합니다.
-
-
navigator. clipboard. readText(). then( function ( data) { console. log( "Your string: " , data); });
7.3.3. write(data)
write(data)
메서드는 다음 단계를 실행해야 한다:
-
p를 realm 내의 새 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
r을 클립보드 쓰기 권한 확인 실행 결과로 둡니다.
clipboard-write는 https://github.com/w3c/clipboard-apis/pull/164 에서 제거되었습니다.
-
r이 false이면:
-
글로벌 태스크 큐잉을 permission task source 위에서, realm의 글로벌 객체로, p를
"NotAllowedError"DOMException으로 realm에서 reject 하게 합니다. -
이 단계를 중단합니다.
-
-
글로벌 태스크 큐잉을 clipboard task source 위에서, realm의 글로벌 객체로, 아래 단계를 실행하도록 합니다:
-
dataList를 시퀀스<
ClipboardItem>로 둡니다. -
만약 data의 크기가 1보다 크고, 현재 운영체제가 시스템 클립보드에서 여러 기본 클립보드 항목을 지원하지 않으면 data[0]을 dataList에 추가하고, 그렇지 않으면 dataList를 data로 설정합니다.
data에 여러 항목이 있고 운영체제가 여러 기본 클립보드 항목을 지원한다면, 현재 알고리즘은 항목들을 집합적으로 기록하는 대신 순차적으로 기록합니다.
-
dataList의 각 clipboardItem에 대해:
-
clipboardItem의 클립보드 항목의 표현 목록의 각 representation에 대해:
-
representationDataPromise를 representation의 data로 둡니다.
-
반응 하기를 representationDataPromise가 완료될 때:
-
representationDataPromise가 값 v로 fulfill된 경우:
-
representationDataPromise가 reject된 경우:
-
p를
"NotAllowedError"DOMException과 함께 realm에서 Reject합니다. -
이 단계를 중단합니다.
-
-
-
-
itemList의 각 blob에 대해:
-
type을 blob의
type으로 둡니다. -
type이 필수 데이터 타입 또는 옵션 데이터 타입 리스트에 없으면, p를
"NotAllowedError"DOMException과 함께 realm에서 reject하고 이 단계를 중단합니다. -
cleanItem을 blob의 (선택적으로 정제된) 복사본으로 둡니다.
-
정제가 시도되었으나 성공적으로 완료되지 않은 경우, 다음 단계를 따르십시오:
-
p를
"NotAllowedError"DOMException 과 함께 realm에서 Reject합니다. -
이 단계를 중단합니다.
-
-
cleanItem을 cleanItemList에 추가합니다.
-
-
option을 clipboardItem의 클립보드 항목의 프레젠테이션 스타일로 둡니다.
-
클립보드에 blobs와 option을 기록을 cleanItemList와 option으로 실행합니다.
-
-
p를 resolve합니다.
-
-
p를 반환합니다.
var data= [ new ClipboardItem({ "text/plain" : Promise. resolve( new Blob([ "Text data" ], { type: "text/plain" })) })]; navigator. clipboard. write( data). then( function () { console. log( "Copied to clipboard successfully!" ); }, function () { console. error( "Unable to write to clipboard. :-(" ); });
7.3.4. writeText(data)
writeText(data)
메서드는 다음 단계를 실행해야 한다:
-
p를 realm 내의 새 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
r을 클립보드 쓰기 권한 확인의 실행 결과로 둡니다.
clipboard-write는 https://github.com/w3c/clipboard-apis/pull/164에서 삭제되었습니다.
-
r이 false이면:
-
글로벌 태스크 큐잉을 permission task source 위에, realm의 글로벌 객체를 넘겨 p를
"NotAllowedError"DOMException과 함께 realm에서 reject 하게 합니다. -
이 단계를 중단합니다.
-
-
글로벌 태스크 큐잉을 clipboard task source 위에, realm의 글로벌 객체를 넘겨 아래 단계를 실행하도록 합니다:
-
textBlob을 새
Blob으로 만듭니다.type속성은 "text/plain;charset=utf-8"로, 그 내부 바이트 시퀀스는 UTF-8 인코딩의 data로 설정합니다.참고: Windows에서는 data를 textBlob으로 만들기 전에 `\n` 문자를 `\r\n`으로 바꿔야 합니다.
-
textBlob을 itemList에 추가합니다.
-
option을 "unspecified"로 설정합니다.
-
클립보드에 blobs 및 옵션 쓰기를 itemList와 option으로 실행합니다.
-
p를 resolve합니다.
-
-
p를 반환합니다.
await navigator. clipboard. writeText( "Howdy, partner!" );
8. 클립보드 동작
이 섹션은 클립보드 동작과 이벤트 디스패치 처리 모델을 정의합니다.
각 클립보드 동작은 스크립트-트리거됨 및 스크립트-클립보드-접근-허용이라는 두 개의 플래그를 가집니다.
스크립트-트리거됨
플래그는 동작이 스크립트로 인해 실행될 때(예: document.execCommand() 호출) 설정됩니다.
클립보드와 상호작용하는 향후 스크립팅 API도 이 플래그를 사용해야 하며,
스크립트-트리거됨 플래그가 올바르게
설정되어야 합니다.
스크립트-클립보드-접근-허용 플래그는 다음과 같이 설정됩니다:
-
동작이 복사 또는 잘라내기이고, 스크립트 스레드가 클립보드 수정 허용이면,
-
동작의 스크립트-클립보드-접근-허용 플래그를 설정한다
-
-
동작이 붙여넣기이고, 스크립트 스레드가 클립보드 읽기 허용이면,
-
동작의 스크립트-클립보드-접근-허용 플래그를 설정한다.
-
8.1. 복사 동작
복사 동작은 다음 단계로 구성됩니다:
-
script-triggered 플래그가 설정되어 있으면,
-
script-may-access-clipboard 플래그가 설정되어 있지 않으면,
-
복사 작업에서 false를 반환하고, 이 알고리즘을 종료합니다.
-
-
-
이벤트가 취소되지 않았다면,
-
선택한 내용(있는 경우)을 클립보드에 복사합니다. 구현체는 웹 페이지에서 내용이 선택되었을 때 대체 text/html 및 text/plain 클립보드 포맷을 생성하는 것이 권장됩니다.
-
"clipboardchange"라는 이름의
clipboardchange클립보드 이벤트를 발생시킵니다.
-
-
그렇지 않고 이벤트가 취소되었다면,
-
클립보드에 내용 쓰기 알고리즘을 호출합니다. 이때
DataTransferItemList리스트 items와 clear-was-called 플래그, types-to-clear 리스트를 전달합니다.
-
-
복사 작업에서 true를 반환합니다.
8.2. 잘라내기 동작
잘라내기 동작은 다음 단계로 구성됩니다:
-
script-triggered 플래그가 설정되어 있다면,
-
script-may-access-clipboard 플래그가 설정 해제되어 있다면,
-
잘라내기 작업에서 false를 반환하고, 이 알고리즘을 종료합니다.
-
-
-
이 이벤트가 취소되지 않았다면,
-
선택 영역이 편집 가능한 컨텍스트 내에서 잘라내기가 활성화된 상태라면,
-
선택된 내용(있는 경우)을 클립보드에 복사합니다. 구현체는 웹 페이지에서 내용이 선택되었을 때 대체 text/html 및 text/plain 클립보드 포맷을 생성하는 것이 권장됩니다.
-
문서에서 해당 선택 영역의 내용을 제거하고 선택 영역을 축소합니다.
-
"clipboardchange"라는 이름의
clipboardchange클립보드 이벤트를 발생시킵니다. -
변경으로 인해 발생해야 하는 모든 이벤트를 큐에 넣어 발생시키십시오. 자세한 내용은 § 5.3 다른 스크립트 및 이벤트와의 통합을 참조하세요.
-
-
그렇지 않고 선택 영역이 없거나, 컨텍스트가 편집 가능하지 않으면,
-
false를 반환합니다.
-
-
-
그 외에, 만약 이벤트가 취소되었다면,
-
클립보드에 내용 쓰기 알고리즘을 호출합니다. 이때
DataTransferItemList리스트 items와, clear-was-called 플래그, types-to-clear 리스트를 넘깁니다. -
"clipboardchange"라는 이름의
clipboardchange클립보드 이벤트를 발생시킵니다.
-
-
잘라내기 작업에서 true를 반환합니다.
8.3. 붙여넣기 동작
붙여넣기 동작에서 스크립트-클립보드-접근-허용 플래그는 어떤 사이트나 앱이 클립보드에서 읽을 수 있는지 결정하기 위한 구현체별 권한 메커니즘에 따라 달라집니다. 붙여넣기 동작이 스크립트로 트리거될 때, 구현체는 사용자의 허락 없이 클립보드 내용을 노출해서는 안 됩니다. 권한이 미리 부여되지 않은 경우, 권한 프롬프트에는 스크립트 스레드에 연결된 문서의 호스트명이 반드시 포함되어야 합니다.
붙여넣기 동작은 다음 단계로 구성됩니다:
-
스크립트-트리거됨 플래그가 설정되어 있으면,
-
스크립트-클립보드-접근-허용 플래그가 설정되어 있지 않으면,
-
붙여넣기 동작에서 false를 반환하고, 알고리즘을 종료한다
-
-
-
이 이벤트가 취소되지 않았으면,
-
editable context에서 붙여넣기가 허용된 선택 영역이나 커서가 존재하면,
-
클립보드에서 찾은 가장 적합한 콘텐츠(있는 경우)를 해당 컨텍스트에 삽입한다.
-
수정으로 인해 발생해야 하는 이벤트들을 큐에 추가한다. 자세한 내용은 § 5.3 다른 스크립트 및 이벤트와의 통합을 참고한다.
-
-
그렇지 않으면
-
false를 반환한다
-
-
-
그렇지 않고 이벤트가 취소되었다면
-
false를 반환한다
-
-
동작에서 true를 반환한다
9. Permissions API 연동
[permissions] API는 웹사이트가 강력한 기능(예: 클립보드)에 접근할 수 있는 통합 방식을 제공합니다. 웹사이트는 사용자의 권한을 요청하고, 어떤 권한을 가지고 있는지 조회할 수 있습니다.
클립보드의 경우, 하나의 권한이 정의되어 있습니다: "clipboard-write"
참고: 클립보드 권한은 현재 비동기 클립보드 API에만 적용됩니다. 향후 이 명세의 버전에서는 다른 클립보드 상호작용에도 이 권한이 적용될 수 있습니다.
다음과 같이 클립보드 권한은 강력한 기능이며, 권한 관련 알고리즘과 타입은 다음과 같이 정의됩니다:
- permission descriptor type
-
dictionary :ClipboardPermissionDescriptor PermissionDescriptor {boolean =allowWithoutGesture false ; };
클립보드 권한은 4가지가 있습니다:
-
{ name: "clipboard-write", allowWithoutGesture: false }
-
{ name: "clipboard-write", allowWithoutGesture: true }
관계는 다음과 같습니다:
-
{ "clipboard-write" + true }는{ "clipboard-write" + false }보다 더 강력합니다.
사용자 에이전트는 반드시 명세서에 설명된 대로 ClipboardPermissionDescriptor
를 지원해야 하지만,
기본 설정과 사용자에게 어떻게 노출하는지는 완전히 제어할 수 있습니다.
-
{ "clipboard-write" + false }는 사용자 제어용으로 노출됨 -
{ "clipboard-write" + true }는 항상거부됨
9.1. 클립보드 읽기 권한
9.1.1. 클립보드 읽기 권한 확인
-
hasGesture를 relevant global object가 this에서 일시적 활성화(transient activation)를 가지고 있으면 true, 그렇지 않으면 false로 한다.
-
hasGesture이면,
-
현재 스크립트가 사용자 에이전트나 OS가 생성한 "Paste" 요소와의 사용자 상호작용 결과로 실행되고 있다면 true를 반환한다.
-
-
false를 반환한다.
9.2. 클립보드 쓰기 권한
9.2.1. 클립보드 쓰기 권한 확인
-
writeWithoutGesture를 permission state({ name: "clipboard-write", allowWithoutGesture: true } 권한 기준)로 한다.
-
writeWithoutGesture가
granted이면 true를 반환한다. -
hasGesture를 this의 관련 글로벌 객체에 일시적 활성화(transient activation)가 있으면 true로, 그렇지 않으면 false로 둡니다.
-
hasGesture이면,
-
현재 스크립트가 사용자 에이전트나 OS가 생성한 "cut" 또는 "copy" 요소와의 사용자 상호작용 결과로 실행되고 있다면 systemCopy를 true로 한다.
-
systemCopy가 true이면 true를 반환한다.
-
request permission to use({ name: "clipboard-write", allowWithoutGesture: false } 권한 기준) 결과를 반환한다.
참고: 사용자 에이전트는 더 강력한 권한을 요청하여 이 권한을 암묵적으로 업데이트할 수도 있습니다.
-
-
request permission to use({ name: "clipboard-write", allowWithoutGesture: true } 권한 기준) 결과를 반환한다.
10. 보안 고려사항
저자가 사용자가 복사하는 내용을 변경하거나, 선택된 적이 없는 내용을 자동으로 복사하거나, 정보 붙여넣기를 제한 없이 호출할 수 있도록 하면 다양한 보안 문제가 발생할 수 있습니다.
예시 시나리오:
-
사용자가 링크를 선택하고 복사했으나, 실제로 다른 링크가 클립보드에 복사됨. 이는 붙여넣기 시 예상치 못한 결과에서 피싱 공격 시도까지 이어질 수 있습니다.
-
(Self-XSS) 셸 명령어나 실행 가능한 스크립트가 클립보드에 삽입되어 사용자가 붙여넣은 후 실행할 수 있습니다.
-
OS의 이미지 처리 코드의 버그를 악용하도록 특별히 제작된 이미지를 클립보드에 쓸 수 있습니다.
10.1. HTML 및 멀티파트 데이터 붙여넣기
이 섹션은 규범적이지 않습니다.
서식 있는 데이터나 멀티파트 데이터를 붙여넣는 데에는 특정 보안 위험이 있습니다.
-
사용자가 보이지 않는 데이터를 인지하지 못한 채 붙여넣을 수 있습니다. 예를 들어, 마크업에 <input type="hidden"> 태그나 HTML 주석이 포함된 경우. 이러한 숨겨진 데이터에는 민감한 정보가 포함될 수 있습니다.
-
사용자가 신뢰하는 페이지에 악성 JavaScript를 붙여넣을 수 있습니다.
-
구현체가 사용자가 공개를 의도하지 않은 로컬 파일에 대한 스크립트 접근을 허용할 수 있습니다.
어떤 정책을 사용할지 결정하기 위해 고려하는 요소는 다음과 같습니다:
-
붙여넣는 데이터의 출처
-
참조된 이미지 등 부분 데이터의 출처
-
실행 중인 스크립트의 출처
각 시나리오와 적용 가능한 보안 정책 개요:
| 데이터 출처 | 스크립트 출처 | 규칙 |
|---|---|---|
| 온라인 소스에서 기원 | 데이터와 동일 | HTML을 정제하지 않음. 로컬 파일 접근 불가. |
| 다른 출처 | 콘텐츠 선택적 정제. 로컬 파일 접근 불가. | |
| 로컬 애플리케이션에서 기원 | 상관 없음 | HTML을 정제하지 않음. 로컬 파일 접근 허용 |
일부 구현체는 서식 있는 텍스트 붙여넣기 관련 위험을 완화하기 위해, 기본적으로 SCRIPT 요소나 javascript: 링크 등 잠재적으로 악성인 콘텐츠를 제거하지만, paste 이벤트 핸들러에서는 원본, 비정제 데이터를 처리할 수 있도록 허용합니다.
10.2. 일반 보안 정책
구현체는 온라인에서 참조된 리소스를 다운로드하거나, 그 내용을 files
리스트나 DataTransferItemList
에 노출해서는 안 됩니다.
클립보드 데이터가 로컬 애플리케이션 출신이 아니라면, 구현체는 참조된 로컬 파일에 대한 접근을 허용해서는 안 됩니다. 예를 들면, 데이터에 <img src="file://localhost/example.jpg">가 포함되어 있고 데이터 출처가 온라인 리소스라면, 구현체는 clipboardData.items 리스트에 example.jpg 항목을 추가해서는 안 됩니다.
10.3. 이미지 트랜스코딩
악성 이미지 데이터가 클립보드에 저장되는 것을 방지하기 위해, 이미지 데이터를 안전한 버전으로 트랜스코딩할 수 있습니다. 이를 통해 웹사이트가 다른 애플리케이션의 보안 취약점을 악용하는 것을 막을 수 있습니다.
구현체는 클립보드에서 읽는 이미지를 트랜스코딩해서는 안 됩니다. 트랜스코딩하면 이미지의 물리적 해상도와 같은 중요한 메타데이터가 손실될 수 있습니다. 이는 <input type=file> 등 웹사이트에서 이미지를 공유하는 다른 방식과도 일치합니다.
10.4. 방해 고려사항
스크립트는 DataTransfer
API를 사용하여 복사 및 잘라내기 이벤트에서 시스템 클립보드의 데이터를 변경함으로써 사용자를 혼란스럽게 하거나 괴롭힐 수 있습니다. 이 명세서는 이런 방해를 방지하려고 하지 않지만, 구현체는
추가 제한을 둘 수 있습니다.
구현체는 스크립트가 클립보드에 과도한 양의 데이터를 저장하려는 시도를 우아하게 처리해야 합니다.
11. 프라이버시 고려사항
이 API들은 사용자의 클립보드 데이터에 접근할 수 있으므로, 이름, 주소, 비밀번호 등 개인정보(PII)가 클립보드에 저장될 수 있어 심각한 프라이버시 문제가 있습니다.
일반적으로, 사용자 에이전트는 신뢰되지 않은 스크립트가 이러한 API를 통해 사용자의 클립보드 데이터를 무제한으로 접근하지 못하도록 반드시 보장해야 합니다.
11.1. 프라이버시와 클립보드 이벤트 API
클립보드 이벤트 API는 클립보드 이벤트 핸들러 컨텍스트에서 실행되는 스크립트가 시스템 클립보드의 복사본에 접근하고, 클립보드에 쓰이는 데이터를 수정할 수 있도록 허용합니다.
사용자 에이전트는 클립보드 이벤트 API를 통해 접근하는 데이터 보안을 위해 다음 요구사항을 인지해야 합니다:
-
DataTransfer인터페이스를 구현하여 클립보드 데이터를 반환하는 객체는 해당 ClipboardEvent 이벤트 핸들러 외부에서는 노출되어서는 안 됩니다. -
스크립트가 ClipboardEvent 이벤트 핸들러 외부에서 사용하기 위해 DataTransfer 인터페이스를 구현한 객체의 참조를 저장한 경우, 그 모든 메서드는 예상된 컨텍스트 외부에서는 동작하지 않아야(no-op) 합니다.
-
구현체는 스크립트가 합성 클립보드 이벤트를 생성해서 실제 클립보드 데이터에 접근하는 것을 허용해서는 안 됩니다 (사용자가 직접 설정한 경우는 예외).
클립보드 이벤트 API는 클립보드 권한에 적용되지 않지만, 사용자 에이전트는 사용자가 이 API를 비활성화하거나 특정 사이트에만 접근을 허용하도록 설정할 수 있는 방법을 제공할 수 있습니다.
11.2. 프라이버시와 비동기 클립보드 API
비동기 클립보드 API는 강력한 기능입니다. 이벤트 핸들러 컨텍스트에 국한되지 않고, 모든 스크립트가 클립보드 데이터에 접근할 수 있으며, 사용자 제스처 없이도 데이터에 접근할 수 있습니다.
남용을 막기 위해, 이 API는 문서가 포커스를 가지고 있을 때만 사용할 수 있어야 합니다.
11.2.1. 프라이버시와 클립보드 권한
클립보드 권한은 이 API 접근을 제한하지만, 사용자 에이전트는 권한의 기본값과 어떤 권한 설정을 사용자가 조정할 수 있을지 선택할 수 있습니다. 예를 들어, 사용자 에이전트는 사용자 제스처가 있는 경우에만 비동기 클립보드 API 접근을 허용하고, 제스처 없는 스크립트 요청은 항상 거부할 수 있습니다.
사용자 에이전트는 사용자가 권한을 부여한 후 권한이 자동으로 만료되도록 선택할 수 있습니다. 예를 들어, 권한 만료 조건은 다음과 같습니다:
-
권한 부여 후 일정 시간이 지나면
-
사용자가 사이트를 마지막으로 방문한 후 일정 시간이 지나면
-
사용자가 페이지를 벗어나면
11.3. 기타 프라이버시 우려
사용자 에이전트가 document.execCommand("paste")를 통해 클립보드 데이터를 읽을 수 있게 허용하는 경우, 반드시 사용자가 명시적으로 접근을 허용했는지
확인해야 합니다.
12. 감사의 글
이 섹션은 규범적이지 않습니다.
에디터들은 이전 에디터들의 기여를 인정합니다. 그들은 이 명세가 지금의 형태에 이르기까지 다양한 회의와 메일링 리스트 논의를 통해 발전시켜 주었습니다.
-
Hallvord R. M. Steen
에디터들은 또한 Microsoft의 Data Transfer 기능 문서 [MICROSOFT-CLIP-OP]와 [HTML5] 명세의 이전 초안에 지적 빚을 졌음을 인정합니다. 또한 Paul Libbrecht의 "safe copy and paste" 초안에도 감사드립니다 (이 초안은 현재 웹에서 제공되지 않습니다).
마지막으로 다음 분들의 기여에 감사드립니다:
Adam Barth, Shawn Carnell, Daniel Cheng, Daniel Dardailler, Domenic Denicola, Al Gilman, James Graham, James Greene, Ian Hickson, Darwin Huang, Lachlan Hunt, Philip Jägenstedt, Anne van Kesteren, Marijn Kruisselbrink, Aaron Leventhal, Jim Ley, Paul Libbrecht, "Martijn", Glenn Maynard, Chris Mills, ms2ger, Ryosuke Niwa, Robert O’Callahan, Dave Poehlman, "ROBO Design", Janina Sajka, Rich Schwerdtfeger, Jonas Sicking, Maciej Stachowiak, Mihai Sucan, Dmitry Titov, Ojan Vafai, Tarquin Wilton-Jones, Tom Wlodkowski, Bo Cupp, mbrodesser 그리고 Boris Zbarsky.
부록 A: 알고리즘
클립보드에 콘텐츠 쓰기
- 입력
-
items :
DataTransferItemList클립보드에 쓸 아이템 리스트clear-was-called : boolean 값
types-to-clear : 리스트
- 출력
-
없음
-
items 리스트가 비어 있지 않으면,
-
클립보드를 비운다
-
리스트의 각 파트에 대해,
-
데이터 타입이 text/plain이면,
-
OS 및 로캘 관례에 따라 인코딩이 올바른지 확인
-
플랫폼 관례에 따라 줄바꿈을 정규화
-
OS 클립보드 포맷 설명에 맞게 텍스트를 클립보드에 넣는다
-
-
그 외, 데이터가 필수 데이터 타입 리스트에 포함된 타입이면,
-
OS 클립보드 포맷 설명에 맞게 파트를 클립보드에 넣는다
-
-
그 외의 경우
-
-
-
그 외, items 리스트가 비어 있다면, 아래와 같이 클립보드를 비울지 결정한다:
블롭과 옵션을 클립보드에 기록하기
- 입력
-
presentationStyle — 클립보드 항목의 프레젠테이션 스타일
- 출력
-
없음
-
items의 각 item에 대해:
-
formatString을 item의
type을 인자로 운영체제 특화 잘 알려진 포맷 알고리즘을 실행한 결과로 둡니다. -
formatString이 비어 있다면 다음 하위 단계를 따릅니다:
-
webCustomFormatString을 item의
type으로 둡니다. -
webCustomFormat을 빈
type으로 둡니다. -
webCustomFormatString이 "web " 접두사로 시작한다면, "web " 접두사를 제거한 나머지 문자열을 webMimeTypeString에 저장합니다.
-
webMimeType을 webMimeTypeString을 인자로 MIME 타입 파싱 알고리즘을 실행한 결과로 둡니다.
-
webMimeType이 실패(failure)이면, 모든 단계를 중단합니다.
-
item의
type을 webCustomFormat으로 설정합니다. -
webCustomFormat을 webCustomFormats에 추가합니다.
-
-
payload를 item의 바이트 시퀀스에 UTF-8 디코딩을 실행한 결과로 둡니다.
-
payload와 presentationStyle을 formatString을 네이티브 클립보드 포맷으로 사용하여 시스템 클립보드에 삽입합니다.
일부 OS(예: Linux "primary", "secondary", "selection")는 여러 클립보드를 가지고 있습니다. 어느 쪽에 데이터를 쓸지 정의해야 합니다.
-
-
웹 커스텀 포맷 쓰기를 webCustomFormats에 대해 실행합니다.
OS별 알려진 포맷
- 입력
-
mimeType :
type - 출력
-
wellKnownFormat : 플랫폼별 문자열 타입 (Mac: NSPasteboardType, Windows: LPCWSTR, Linux: const char*)
Windows: https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats 및 https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables?redirectedfrom=MSDN Mac: https://developer.apple.com/documentation/appkit/nspasteboardtype
-
wellKnownFormat을 빈 문자열로 한다.
-
mimeType의 essence가 "text/plain"이면,
Windows에서는 다음과 같이:
-
wellKnownFormat에 CF_UNICODETEXT 할당
MacOS에서는 다음과 같이:
-
wellKnownFormat에 NSPasteboardTypeString 할당
Linux, ChromeOS, Android에서는 다음과 같이:
-
wellKnownFormat에 "text/plain" 할당
-
-
그 외, mimeType의 essence가 "text/html"이면,
Windows에서는 다음과 같이:
-
wellKnownFormat에 CF_HTML 할당
MacOS에서는 다음과 같이:
-
wellKnownFormat에 NSPasteboardTypeHTML 할당
Linux, ChromeOS, Android에서는 다음과 같이:
-
wellKnownFormat에 "text/html" 할당
-
-
그 외, mimeType의 essence가 "image/png"이면,
Windows에서는 다음과 같이:
-
wellKnownFormat에 "PNG" 할당
MacOS에서는 다음과 같이:
-
wellKnownFormat에 NSPasteboardTypePNG 할당
Linux, ChromeOS, Android에서는 다음과 같이:
-
wellKnownFormat에 "image/png" 할당
-
-
그 외, mimeType의 essence가 "image/svg+xml"이면,
Windows에서는 다음과 같이:
-
wellKnownFormat에 CFSTR_MIME_SVG_XML 할당
MacOS에서는 다음과 같이:
-
wellKnownFormat에 UTTypeSVG 할당
Linux, ChromeOS, Android에서는 다음과 같이:
-
wellKnownFormat에 "image/svg+xml" 할당
-
-
wellKnownFormat을 반환한다.
OS별 포맷에서 알려진 MIME 타입
- 입력
-
osFormatName : 플랫폼별 문자열 타입 (Mac: NSPasteboardType, Windows: LPCWSTR, Linux: const char*)
- 출력
-
mimeType : MIME type
Windows: https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats 및 https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables?redirectedfrom=MSDN Mac: https://developer.apple.com/documentation/appkit/nspasteboardtype
Windows에서는 다음과 같이:
-
osFormatName이 "UnicodeText"면 mimeTypeString을 "text/plain"으로 설정
-
그 외, osFormatName이 "HTML Format"이면 mimeTypeString을 "text/html"로 설정
-
그 외, osFormatName이 "PNG"이면 mimeTypeString을 "image/png"로 설정
-
그 외, osFormatName이 CFSTR_MIME_SVG_XML이면 mimeTypeString을 "image/svg+xml"로 설정
MacOS에서는 다음과 같이:
-
osFormatName이 NSPasteboardTypeString이면 mimeTypeString을 "text/plain"으로 설정
-
그 외, osFormatName이 NSPasteboardTypeHTML이면 mimeTypeString을 "text/html"로 설정
-
그 외, osFormatName이 NSPasteboardTypePNG이면 mimeTypeString을 "image/png"로 설정
-
그 외, osFormatName이 UTTypeSVG이면 mimeTypeString을 "image/svg+xml"로 설정
Linux, ChromeOS, Android에서는 다음과 같이:
-
osFormatName이 "text/plain"이면 mimeTypeString을 "text/plain"으로 설정
-
그 외, osFormatName이 "text/html"이면 mimeTypeString을 "text/html"로 설정
-
그 외, osFormatName이 "image/png"이면 mimeTypeString을 "image/png"로 설정
-
그 외, osFormatName이 "image/svg+xml"이면 mimeTypeString을 "image/svg+xml"로 설정
-
mimeType을 MIME 타입 파싱(mimeTypeString 기준) 결과로 한다.
-
mimeType을 반환한다.
웹 커스텀 포맷 읽기
- 입력
-
item, 클립보드 아이템
-
webCustomFormatMap을 OS별 커스텀 포맷 맵 이름으로 한다.
-
webCustomFormatMap을 시스템 클립보드에서 읽는다.
-
webCustomFormatMap이 비어 있으면 item을 반환한다.
-
webCustomFormatMapString을 webCustomFormatMap에서 역직렬화한 JSON 문자열로 한다.
참고: webCustomFormatMap의 내용을 역직렬화할 JSON 리더 필요.
-
webCustomFormatMapString의 각 (key, value)에 대해:
-
mimeType을 MIME 타입 파싱(key 기준) 결과로 한다.
-
mimeType이 실패이면 루프 계속.
-
representation을 새로운 representation으로 한다.
-
representation의 MIME type을 mimeType으로 설정.
-
representation의 isCustom 플래그를 true로 설정.
-
webCustomFormat을 시스템 클립보드에서 value로 읽는다.
-
읽기 성공 시 representation의 data를 시스템 클립보드에서 가져온 데이터로 설정, 실패 시 루프 계속.
-
representation을 item의 list of representations에 추가.
-
웹 커스텀 포맷 쓰기
-
idx를 0으로 초기화.
-
webCustomFormatMap을 OS별 커스텀 포맷 맵 이름으로 한다.
-
webCustomFormatMapString을 빈 JSON 문자열로 한다.
-
items의 각 item에 대해:
-
webCustomFormat을 OS별 커스텀 포맷 이름으로 한다.
-
webCustomFormatIdx를 idx를 webCustomFormat에 붙인 결과로 한다.
-
item의
type을 key로, webCustomFormatIdx을 value로 하여 webCustomFormatMapString에 JSON serializer로 삽입.참고: webCustomFormatMapString으로 직렬화할 JSON writer 필요.
-
item을 시스템 클립보드에 webCustomFormatIdx 포맷으로 삽입.
-
idx를 증가.
-
idx가 100보다 크면 루프 종료.
-
-
webCustomFormatMapString을 시스템 클립보드에 webCustomFormatMap 포맷으로 삽입.
OS별 커스텀 포맷 맵 이름
- 출력
-
webCustomFormatMap, 문자열
Windows에서는 다음과 같이:
-
webCustomFormatMap에 "Web Custom Format Map" 할당.
-
webCustomFormatMap 반환.
MacOS에서는 다음과 같이:
-
webCustomFormatMap에 "org.w3.web-custom-format.map" 할당.
-
webCustomFormatMap 반환.
Linux, ChromeOS, Android에서는 다음과 같이:
-
webCustomFormatMap에 "application/web;type=\"custom/formatmap\"" 할당.
-
webCustomFormatMap 반환.
운영체제별 커스텀 이름
- 출력
-
webCustomFormat, 문자열
Windows에서는 다음 기준을 따른다:
-
webCustomFormat에 "Web Custom Format"을 할당한다.
-
webCustomFormat을 반환한다.
MacOS에서는 다음 기준을 따른다:
-
webCustomFormat에 "org.w3.web-custom-format.type-"을 할당한다.
-
webCustomFormat을 반환한다.
Linux, ChromeOS, Android에서는 다음 기준을 따른다:
-
webCustomFormat에 "application/web;type="custom/format"을 할당한다.
-
webCustomFormat을 반환한다.
클립보드 이벤트 발생시키기
- 입력
-
e,
ClipboardEvent발생시킬 이벤트 - 출력
-
없음
-
clear-was-called을 false로 한다.
-
types-to-clear를 빈 리스트로 한다.
-
clipboard-event-data를 새로운
DataTransfer객체로,items리스트는 빈 값으로 생성한다. -
clipboard-entry를 현재 클립보드 콘텐츠의 시퀀스 번호로 하거나, OS 클립보드가 시퀀스 번호를 지원하지 않는 경우 null로 한다.
-
trusted를 이벤트가 사용자 에이전트에 의해 생성된 경우 true, 그렇지 않으면 false로 한다.
-
target을 다음과 같이 설정한다:
-
이벤트를 다음과 같이 처리한다:
-
e가 "paste"이면,
-
clipboard-event-data의 내부 drag data store mode 플래그를 read-only로 설정한다.
-
trusted가 true이거나, 구현체가 스크립트 생성 이벤트에 OS 클립보드 읽기 권한을 부여하도록 설정된 경우,
-
OS 클립보드의 각 clipboard-part에 대해 아래를 수행한다:
-
clipboard-part가 평문 텍스트를 포함하면,
-
텍스트가 스크립트 엔진 내부 인코딩에 맞는지 확인한다.
-
new-data를 새로운
DataTransferItem으로, drag data item kind는 string, drag data item type string은 text/plain으로 한다. -
new-data의 데이터를 평문 텍스트로 설정한다.
-
new-data를 clipboard-event-data의
items리스트에 추가한다.
-
-
clipboard-part가 파일 참조를 나타내면, 각 파일 참조에 대해:
-
참조된 파일의 MIME 타입을 결정한다.
-
new-data를 새로운
DataTransferItem으로, drag data item kind는 file, drag data item type string은 해당 MIME 타입(모르면application/octet-stream)으로 한다. -
new-data의 데이터를 파일 참조 데이터로 설정한다.
-
new-data를 clipboard-event-data의
items리스트에 추가한다.
-
-
clipboard-part가 HTML 또는 XHTML 형식의 텍스트를 포함하면(OS 클립보드 포맷 설명 기준),
-
구현체가 HTML 붙여넣기를 지원하면, HTML 붙여넣기 이벤트 처리(clipboard-part, clipboard-event-data)를 호출한다.
-
-
clipboard-part가 다른 지원되는 바이너리 혹은 텍스트 기반 포맷(see 필수 데이터 타입)의 데이터를 포함하면,
-
데이터의 MIME 타입 결정
-
new-data를 새로운
DataTransferItem으로, drag data item kind는 file, drag data item type string은 해당 MIME 타입으로 한다. -
new-data의 데이터를 바이너리 또는 텍스트 기반 데이터로 설정한다.
-
new-data를 clipboard-event-data의
items리스트에 추가한다.
-
-
-
-
clipboard-event-data의
files속성을 clipboard-event-data의items항목에 맞게 갱신한다. -
clipboard-event-data의
types속성을 clipboard-event-data의items항목에 맞게 갱신한다.
-
-
e가 "copy" 또는 "cut"이면,
-
해당
DataTransfer객체의 내부 drag data store mode 플래그를 read/write로 한다.
-
-
-
e의
clipboardData를 clipboard-event-data로 설정한다. -
e의
isTrusted를 trusted로 설정한다. -
e의
composed를 true로 설정한다. -
이벤트 e를 target에 버블링되고 취소 가능한 이벤트로,
ClipboardEvent인터페이스로 디스패치한다.이벤트 디스패치 중 데이터 접근에 대한 구현 요구사항은 [HTML]에 정의되어 있다. 추가적인 클립보드 이벤트 전용 처리 규칙은 아래와 같다:
왜 여기서 정의하는가? 왜 HTML 명세에 포함되지 않는가?
-
스크립트가 clearData() 또는
clear()를 호출하고,DataTransfer객체 내부 drag data store mode 플래그가 read/write이면,-
clear-was-called 플래그를 true로 설정한다. 인자가 주어지면 해당 인자를 types-to-clear 리스트에 추가한다.
-
-
스크립트가 setData()를 호출하거나 아이템을 수정하고, clear-was-called 플래그가 true이면,
-
types-to-clear 리스트가 비어있으면,
-
clear-was-called 플래그를 false로 한다.
-
-
그 외, setData()의
type인자 또는 새 아이템의 drag data item type string이 types-to-clear 리스트에 있다면,-
리스트에서 해당 항목을 제거하고, 리스트가 비어있으면 clear-was-called 플래그를 false로 한다.
-
-
-
스크립트가 getData()를 호출하거나
DataTransferItemList에 접근하고 clipboard-entry가 설정되어 있으면,-
클립보드 데이터의 시퀀스 번호가 clipboard-entry와 일치하는지 확인한다. 클립보드가 더 이상 동일한 항목을 포함하지 않으면
DataTransferItemList객체의 내부 drag data store mode를 protected로 설정한다.
-
경고! paste 이벤트를 감시하는 악성 스크립트가 사용자가 미래에 클립보드에 넣는 것을 무한 반복 루프를 통해 읽을 수 있습니다. 클립보드 시퀀스 번호를 지원하지 않는 플랫폼에서는 추가 제한이 필요합니다.
-
HTML 붙여넣기 이벤트 처리
- 입력
-
clipboard-part, 처리할 클립보드 파트
clipboard-event-data, 이 이벤트용
DataTransfer객체 - 출력
-
없음
-
new-data를 새로운
DataTransferItem으로, drag data item kind는 Plain Unicode string, drag data item type string은 text/html 또는 application/xhtml+xml로 한다. -
clipboard-part에서 마크업을 추출하고, 관련 파서를 사용해 DOM 트리를 생성한다.
-
마크업의 소스 URL이 알려져 있다면, HREF와 SRC 속성의 상대 URL을 소스 URL을 기준으로 모두 절대 URL로 변환해 해당 속성에 설정한다.
-
마크업의 출처가 로컬 애플리케이션이라면, 로컬 파일이나 OS 클립보드의 다른 부분을 참조하는지 확인한다. 참조가 있다면, 서브파트 참조는 반드시 cid: URL 스킴([RFC2392])을 활용해 content-id 참조로 바꿔야 한다. 이를 위해 아래 단계를 따른다:
이 단계가 필요한가? 내부 참조가 있는 다중 파트 지원 네이티브(플랫폼) 클립보드 구현이 존재하는가?
이 기능은 꼭 필요한지, 그리고 크로스 플랫폼 테스트가 어렵기 때문에 위험에 처해있음.
-
clipboard-event-data의
items에 이미 참조된 파일 또는 클립보드 파트에 대한 항목이 있으면,-
itemNumber를 해당 항목의 인덱스로 설정한다.
-
-
그렇지 않으면,
-
new-file-data를 새
DataTransferItem객체로 하고, drag data item kind는 "file"로, drag data item type string은 파일 또는 클립보드 파트의 MIME 타입(알 수 없다면application/octet-stream)으로 설정한다. -
file-info를 새
File객체로 하며,name은 HTML 속성 값의 이름 부분으로,lastModified는 참조된 파일의 타임스탬프 또는 클립보드 파트라면 0으로 설정한다. -
new-file-data의 내부
File객체를 file-info로 설정한다. -
new-file-data를 clipboard-event-data의
items에 추가하고, itemNumber를DataTransferItemList에서 해당 항목의 인덱스로 한다.
-
-
로컬 파일 또는 클립보드 파트를 참조하는 DOM 속성을 'cid:'와 itemNumber로 갱신한다.
-
-
처리된 DOM을 직렬화하여 new-data에 생성된 HTML 코드로 갱신한다.
-
new-data를 clipboard-event-data의
items에 추가한다.