Selkies

lib/clipboard-sync

Client/server clipboard synchronization, shared by both transports.

The pieces are factories the cores compose: createClipboardSync owns the server-clipboard cache and the change-only signature (unchanged content never re-crosses the transport in either direction), createIncomingClipboard is the server-to-client path (reassembly through createMultipartClipboardState, the cache, and the local write, issued when a payload is announced), createSecretClipboardGuard takes a secret the session copied back off the local clipboard, createTaggedClipboardFetch marks the connect-time cache-only fetch, createLocalClipboardSender is the focus-driven local-to-server path, createDeferredClipboardWriter keeps a write the engine refused (no focus, no user activation) for the next gesture, localClipboardBlocker names what stops a local write at all, and createClipboardGestures wires the copy and paste keystrokes. The transports differ only in the hooks they inject: how a request or payload is sent and the enablement gates, which are closures re-read per event so runtime settings changes apply immediately.

Interfaces

MultipartClipboardState

Defined in: lib/clipboard-sync.js:182

Properties

begin
begin: (mime, total) => void;

Defined in: lib/clipboard-sync.js:183

Arms a transfer.

Parameters
ParameterType
mimestring
totalnumber
Returns

void

push
push: (b64) => void;

Defined in: lib/clipboard-sync.js:184

Hands one base64 chunk to the worker.

Parameters
ParameterType
b64string
Returns

void

finish
finish: () => Promise<{
  result: any;
  mimeType: string;
  byteLength: number;
}>;

Defined in: lib/clipboard-sync.js:185

Resolves with the decoded payload and resets; rejects when no transfer is in progress.

Returns

Promise<{ result: any; mimeType: string; byteLength: number; }>

reset
reset: () => void;

Defined in: lib/clipboard-sync.js:188

Drops the transfer.

Returns

void

inProgress
inProgress: boolean;

Defined in: lib/clipboard-sync.js:189

mimeType
mimeType: string;

Defined in: lib/clipboard-sync.js:190

totalSize
totalSize: number;

Defined in: lib/clipboard-sync.js:191

Declared size in bytes.

receivedSize
receivedSize: number;

Defined in: lib/clipboard-sync.js:192

Decoded bytes accumulated so far.


TaggedClipboardFetch

Defined in: lib/clipboard-sync.js:261

Properties

arm
arm: () => void;

Defined in: lib/clipboard-sync.js:262

Records that the server tags the reply.

Returns

void

armLegacyWindow
armLegacyWindow: (ms) => void;

Defined in: lib/clipboard-sync.js:263

Starts the timed fallback after sending cr.

Parameters
ParameterType
msnumber
Returns

void

consume
consume: () => boolean;

Defined in: lib/clipboard-sync.js:265

Whether the next payload is the fetch reply.

Returns

boolean


LocalClipboardSender

Defined in: lib/clipboard-sync.js:326

Properties

readAndSend
readAndSend: () => Promise<void>;

Defined in: lib/clipboard-sync.js:327

Reads the local clipboard and pushes any content to the server.

Returns

Promise<void>

sendExplicit
sendExplicit: (data, mime?, onSkip?) => Promise<void>;

Defined in: lib/clipboard-sync.js:329

Pushes content the user named, outranking a concurrent readAndSend.

Parameters
ParameterType
datastring | ArrayBuffer | Blob
mime?string
onSkip?Function
Returns

Promise<void>

maybeInitial
maybeInitial: () => Promise<void>;

Defined in: lib/clipboard-sync.js:331

The connect-time send: once a page, and again at a connection after a read whose push found none.

Returns

Promise<void>

getSendInFlight
getSendInFlight: () => Promise<void>;

Defined in: lib/clipboard-sync.js:333

The send the paste-ordering hold awaits, or null.

Returns

Promise<void>


DeferredClipboardWriter

Defined in: lib/clipboard-sync.js:508

Properties

write
write: (attempt, options?) => Promise<boolean>;

Defined in: lib/clipboard-sync.js:509

Runs an async clipboard write now, stashing it for the next gesture on an activation rejection. settled, when given, resolves once the write's payload is complete.

Parameters
ParameterType
attempt() => Promise<void>
options?{ onSuccess?: () => void | Promise<any>; onFailure?: (err) => void; settled?: Promise<any>; }
options.onSuccess?() => void | Promise<any>
options.onFailure?(err) => void
options.settled?Promise<any>
Returns

Promise<boolean>

flush
flush: () => void;

Defined in: lib/clipboard-sync.js:513

Retries the stashed write.

Returns

void

getInFlight
getInFlight: () => Promise<boolean>;

Defined in: lib/clipboard-sync.js:514

The most recent attempt, immediate or flushed, or null.

Returns

Promise<boolean>

getLanding
getLanding: () => Promise<boolean>;

Defined in: lib/clipboard-sync.js:516

The most recent attempt once its payload is complete, or null.

Returns

Promise<boolean>

hasPending
hasPending: () => boolean;

Defined in: lib/clipboard-sync.js:518

Whether a write is stashed or in flight.

Returns

boolean

issued
issued: () => number;

Defined in: lib/clipboard-sync.js:519

How many writes have been issued, which tells whether one was issued since a given moment.

Returns

number


SecretClipboardGuard

Defined in: lib/clipboard-sync.js:626

Properties

landed
landed: (text) => void;

Defined in: lib/clipboard-sync.js:627

A secret reached the local clipboard: it is taken back once its time is up.

Parameters
ParameterType
textstring
Returns

void

holds
holds: (text) => boolean;

Defined in: lib/clipboard-sync.js:629

Whether text is the secret being watched.

Parameters
ParameterType
textstring
Returns

boolean

retract
retract: () => void;

Defined in: lib/clipboard-sync.js:631

The session's clipboard moved on: the secret is taken back now.

Returns

void


IncomingClipboard

Defined in: lib/clipboard-sync.js:721

Properties

begin
begin: (mime, total, cacheOnly, secret?) => void;

Defined in: lib/clipboard-sync.js:722

Announces a multipart payload of total bytes.

Parameters
ParameterType
mimestring
totalnumber
cacheOnlyboolean
secret?boolean
Returns

void

push
push: (b64) => void;

Defined in: lib/clipboard-sync.js:724

Hands one base64 chunk on.

Parameters
ParameterType
b64string
Returns

void

finish
finish: () => void;

Defined in: lib/clipboard-sync.js:725

Ends the multipart payload.

Returns

void

single
single: (mime, b64, cacheOnly, secret?) => void;

Defined in: lib/clipboard-sync.js:726

Takes a whole payload carried by one message.

Parameters
ParameterType
mimestring
b64string
cacheOnlyboolean
secret?boolean
Returns

void

markSecret
markSecret: () => void;

Defined in: lib/clipboard-sync.js:728

Marks the next payload secret, for a transport that says so in a message of its own ahead of it.

Returns

void

copySecret
copySecret: () => Promise<boolean>;

Defined in: lib/clipboard-sync.js:730

Writes the session's secret to the local clipboard, inside the gesture of a user who asked for it.

Returns

Promise<boolean>

reset
reset: () => void;

Defined in: lib/clipboard-sync.js:732

Drops a payload in progress.

Returns

void


ClipboardSync

Defined in: lib/clipboard-sync.js:1099

Properties

sig
sig: (data, mime?) => string;

Defined in: lib/clipboard-sync.js:1100

Content signature.

Parameters
ParameterType
datastring | ArrayBuffer | Blob | Uint8Array<ArrayBufferLike>
mime?string
Returns

string

shouldSend
shouldSend: (data, mime?) => boolean;

Defined in: lib/clipboard-sync.js:1102

Change-only gate.

Parameters
ParameterType
datastring | ArrayBuffer | Blob | Uint8Array<ArrayBufferLike>
mime?string
Returns

boolean

markSynced
markSynced: (data, mime?) => void;

Defined in: lib/clipboard-sync.js:1104

Records content as synced, on transfer success.

Parameters
ParameterType
datastring | ArrayBuffer | Blob | Uint8Array<ArrayBufferLike>
mime?string
Returns

void

localSig
localSig: (data, mime?) => Promise<string>;

Defined in: lib/clipboard-sync.js:1106

Signature of content read from the local clipboard.

Parameters
ParameterType
datastring | ArrayBuffer
mime?string
Returns

Promise<string>

noteLocal
noteLocal: (s) => boolean;

Defined in: lib/clipboard-sync.js:1108

Records what the local clipboard holds now; whether that differs from what it held before.

Parameters
ParameterType
sstring
Returns

boolean

noteExplicit
noteExplicit: () => void;

Defined in: lib/clipboard-sync.js:1110

Records that a push the user asked for made whatever the local clipboard holds older than the session's.

Returns

void

forget
forget: () => void;

Defined in: lib/clipboard-sync.js:1112

Forgets the synced value and what the local clipboard held, once this page emptied the local clipboard.

Returns

void

forgetLocal
forgetLocal: (s) => void;

Defined in: lib/clipboard-sync.js:1114

Forgets that the local clipboard held s, where its push never left, so the next read sends it.

Parameters
ParameterType
sstring
Returns

void

echoes
echoes: (text) => boolean;

Defined in: lib/clipboard-sync.js:1116

Whether a local read's text is the value last synced in either direction, come back in another form.

Parameters
ParameterType
textstring
Returns

boolean

resolveServer
resolveServer: (text?, blob?, mime?, bytes?) => void;

Defined in: lib/clipboard-sync.js:1118

Caches fresh server data and settles pending requests.

Parameters
ParameterType
text?string
blob?Blob
mime?string
bytes?Uint8Array
Returns

void

captureLocalImageSig
captureLocalImageSig: () => Promise<void>;

Defined in: lib/clipboard-sync.js:1120

Records the browser's re-encoded form of the image just written locally, digesting it through the worker where the caller supplied one.

Returns

Promise<void>

request
request: (wantBinary) => Promise<string | Blob>;

Defined in: lib/clipboard-sync.js:1123

Requests the server clipboard.

Parameters
ParameterType
wantBinaryboolean
Returns

Promise<string | Blob>

copyViaExecCommand
copyViaExecCommand: (textPromise) => Promise<void>;

Defined in: lib/clipboard-sync.js:1125

Last-resort copy through execCommand.

Parameters
ParameterType
textPromisePromise<string>
Returns

Promise<void>

lastText
lastText: string;

Defined in: lib/clipboard-sync.js:1127

lastBlob
lastBlob: Blob;

Defined in: lib/clipboard-sync.js:1128

lastMime
lastMime: string;

Defined in: lib/clipboard-sync.js:1129

Type Aliases

LocalClipboardContent

type LocalClipboardContent = 
  | {
  kind: "text";
  text: string;
}
  | {
  kind: "image";
  blob: Blob;
  mime: string;
};

Defined in: lib/clipboard-sync.js:29

Type Parameters

Type Parameter

Variables

CLIPBOARD_FLAVOURS_MIME

const CLIPBOARD_FLAVOURS_MIME: "application/x-selkies-clipboard-flavours" = 'application/x-selkies-clipboard-flavours';

Defined in: lib/clipboard-sync.js:94

Wire type for a copy carrying more than one flavour: the markup and the plain text its source wrote for it, as a JSON object of mime to content. It never reaches a clipboard itself; the flavours inside it do.


SECRET_CLIPBOARD_TTL_MS

const SECRET_CLIPBOARD_TTL_MS: 60000 = 60000;

Defined in: lib/clipboard-sync.js:623

How long a secret the session copied may stay on the local clipboard.


CLIPBOARD_PREVIEW_LIMIT

const CLIPBOARD_PREVIEW_LIMIT: number;

Defined in: lib/clipboard-sync.js:1070

Longest server clipboard text the dashboards are shown, in characters.

Functions

digestedPayload()

function digestedPayload(byteLength, hash): object;

Defined in: lib/clipboard-sync.js:44

A payload the clipboard worker has already digested, standing in for its bytes wherever a signature is taken.

The worker walks every byte of a clipboard payload anyway, to decode or encode it, and digests it on the way through; passing the result here is what keeps the page from running the same per-byte loop over a payload of any size, several times per transfer.

Parameters

ParameterTypeDescription
byteLengthnumberSize of the payload.
hashnumberIts digest, seeded and computed as hashBytes does.

Returns

object

byteLength
byteLength: number;
hash
hash: number;

reencodeBlobAsPng()

function reencodeBlobAsPng(blob): Promise<Blob>;

Defined in: lib/clipboard-sync.js:58

Re-encodes a raster blob as PNG.

Chromium's async clipboard accepts only image/png on write, but a source may offer only JPEG, BMP, or WebP, so the blob is decoded with the browser's own decoders and re-encoded first.

Parameters

ParameterTypeDescription
blobBlobThe image.

Returns

Promise<Blob>

The PNG.

Throws

When the blob is undecodable (a dimensionless SVG) or the encode fails.


localClipboardBlocker()

function localClipboardBlocker(): string;

Defined in: lib/clipboard-sync.js:82

Why the browser cannot be asked to write the local clipboard, or null when it can.

Both engines expose navigator.clipboard in a secure context only, so a deployment served over http:// on anything but localhost has no clipboard API at all: a server image then lands nowhere, and saying so is the difference between a bug report and a certificate.

Returns

string

The reason, ready to show.


packClipboardFlavours()

function packClipboardFlavours(__namedParameters): ArrayBuffer;

Defined in: lib/clipboard-sync.js:97

The wire payload for one copy's flavours.

Parameters

ParameterType
__namedParameters{ html: any; text: any; }
__namedParameters.htmlany
__namedParameters.textany

Returns

ArrayBuffer


unpackClipboardFlavours()

function unpackClipboardFlavours(bytes): object;

Defined in: lib/clipboard-sync.js:104

The flavours a wire payload carries, as {html, text}.

Parameters

ParameterType
bytesany

Returns

object

html
html: any;
text
text: any;

textOfMarkup()

function textOfMarkup(html): string;

Defined in: lib/clipboard-sync.js:117

The text a markup flavour reads as, for a copy whose source wrote no plain text beside it: the item's types are declared before its data arrive, so it carries a plain flavour either way, and an empty one would paste nothing into a plain field.

Parameters

ParameterTypeDescription
htmlstringThe markup.

Returns

string


readLocalClipboard()

function readLocalClipboard(binaryEnabled): Promise<LocalClipboardContent>;

Defined in: lib/clipboard-sync.js:135

Reads the local clipboard for the focus and gesture send path.

Chromium's read()/getType() throw DataError on large text and some images while readText() still returns the text, so every such failure falls back to it rather than dropping the sync.

Parameters

ParameterTypeDescription
binaryEnabledbooleanWhether images may be read.

Returns

Promise<LocalClipboardContent>

The content, or null when empty.

Throws

Only genuinely unexpected errors, for the caller to log.


createMultipartClipboardState()

function createMultipartClipboardState(openStream): MultipartClipboardState;

Defined in: lib/clipboard-sync.js:209

Multipart server-to-client clipboard download state.

Chunks go straight to the worker as they arrive and the decoded byte count is tracked from their base64 lengths, so a multi-MB clipboard is never held on the main thread, let alone joined into one string there and copied again into the message carrying it off. A truncated stream must never be delivered as content: callers compare receivedSize against totalSize before finishing, or the decoded byte length after, and discard on a mismatch.

Parameters

ParameterTypeDescription
openStream(mime) => objectOpens the worker-side accumulation for one transfer.

Returns

MultipartClipboardState


createTaggedClipboardFetch()

function createTaggedClipboardFetch(): TaggedClipboardFetch;

Defined in: lib/clipboard-sync.js:278

Tracker for the connect-time cache-only clipboard fetch (cr).

The reply must populate the sync cache and preview but never be written to the local clipboard, which would clobber whatever the user copied just before connecting. A tagging server marks the answering payload deterministically; for a server that never tags, a short timed window stands in, so a dropped reply cannot swallow a later genuine push.

Returns

TaggedClipboardFetch


createLocalClipboardSender()

function createLocalClipboardSender(hooks): LocalClipboardSender;

Defined in: lib/clipboard-sync.js:367

Focus and gesture driven local-to-server clipboard sync.

readAndSend is serialized so the paste-ordering hold can hold Ctrl/Cmd+V until the send settles. maybeInitial covers a focused Chromium tab, which gets no focus event after connect and would otherwise leave the server on its stale clipboard until the first alt-tab; it runs only when clipboard read is already granted, since it must never raise a prompt at load.

sendExplicit carries the dashboard's own pushes -- the clipboard box and the image upload -- and outranks a read while it runs and briefly after: choosing a file blurs the page and refocuses it, and the read that refocus fires would put the local clipboard straight back over the upload. It reads a Blob itself, so the push is on record from the call rather than from whenever its bytes arrive; a copy made later reaches the session on the next focus or paste.

Parameters

ParameterTypeDescription
hooks{ isChromium: boolean; isSharedMode: () => boolean; canSync: () => boolean; canRead: () => boolean; binaryEnabled: () => boolean; sendClipboardData: (data, mime?, onSkip?) => Promise<void>; clipboardSync: ClipboardSync; getDeferredWriteInFlight?: () => Promise<any>; }-
hooks.isChromiumbooleanEngine flag.
hooks.isSharedMode() => booleanViewer sessions never send.
hooks.canSync() => booleanClipboard sync enabled.
hooks.canRead() => booleanLocal-to-server direction enabled.
hooks.binaryEnabled() => booleanWhether images are sent.
hooks.sendClipboardData(data, mime?, onSkip?) => Promise<void>Transport send.
hooks.clipboardSyncClipboardSyncThe clipboard state, which knows what the local clipboard last held.
hooks.getDeferredWriteInFlight?() => Promise<any>The deferred writer's pending write, awaited before reading.

Returns

LocalClipboardSender


explicitHasPrecedence()

function explicitHasPrecedence(): boolean;

Defined in: lib/clipboard-sync.js:386

Whether a push the user asked for is still the session's latest word.

Returns

boolean


asSendInFlight()

function asSendInFlight(work): Promise<void>;

Defined in: lib/clipboard-sync.js:392

Runs work as the send the paste-ordering hold waits on.

Parameters

ParameterType
workany

Returns

Promise<void>


readAndSend()

function readAndSend(): Promise<void>;

Defined in: lib/clipboard-sync.js:420

Reads the local clipboard and sends it when it holds something the page has not seen there before.

Content already read or written here is older than whatever the session took since -- an upload, or a session copy whose local write the browser refused -- so sending it again would put a stale value over a newer one; only a change is the user's latest copy. A read while a push the user asked for has precedence still records what it found, so the clipboard the user had before the upload never counts as a change.

A server push still settling through the deferred writer must land before this read: reading around it returns the pre-push content, which would then read as a change. The wait is bounded, since a push whose bytes stopped arriving never settles.

Returns

Promise<void>


sendExplicit()

function sendExplicit(
   data, 
   mime, 
   onSkip
): Promise<void>;

Defined in: lib/clipboard-sync.js:477

Pushes content the user named. A Blob is read here, so the push counts from this call rather than from whenever its bytes arrive.

Parameters

ParameterType
dataany
mimeany
onSkipany

Returns

Promise<void>


createDeferredClipboardWriter()

function createDeferredClipboardWriter(): DeferredClipboardWriter;

Defined in: lib/clipboard-sync.js:545

Deferred local-clipboard writer for server pushes.

Engines decide whether a clipboard write may happen when write() is called: Chromium rejects it from an unfocused document, Firefox and WebKit without a user activation a few seconds old at most, and a server push handler holds neither once the user has moved on. On such a rejection the write is stashed and retried on the next real gesture instead of being lost. Only the newest write is kept, since the clipboard is last-value-wins: issuing a write drops any older stash whatever becomes of it, and a write refused after a newer one was issued is dropped rather than stashed, so no retry can land an older value over a newer one. An attempt rejected with AbortError was withdrawn by its caller and is neither stashed nor reported. The paste-ordering hold awaits the landing attempt (getLanding) so a server-to-client write lands before a paste reads the local clipboard; otherwise the stash flushes on the paste's own keydown and lands just after the read, and the first paste is one behind. The flush rides keydown and pointerdown, which carry a user activation, and focus and visibilitychange, which land the write the instant Chromium accepts it again, well before the user's next paste.

Returns

DeferredClipboardWriter


attemptOnce()

function attemptOnce(w): Promise<boolean>;

Defined in: lib/clipboard-sync.js:574

Runs one write. An activation rejection (a synthetic event, or a blurred tab) stashes it for the next gesture unless a newer write was issued meanwhile, which the stash would otherwise land over once flushed; any other error but a withdrawal reaches onFailure. The attempt settles only after onSuccess has, so whoever waits on it also waits for what the landing set off.

The attempt is started inside a promise chain so that a caller passing a plain expression -- navigator.clipboard.write(...), which throws outright where the browser exposes no clipboard -- fails the same way an async one does, instead of throwing past onFailure.

Parameters

ParameterType
wany

Returns

Promise<boolean>


write()

function write(attempt, __namedParameters?): Promise<boolean>;

Defined in: lib/clipboard-sync.js:604

Runs attempt now; on an activation or focus rejection queues it for the next gesture. onSuccess fires whenever the write eventually lands, onFailure only for errors that are neither activation nor withdrawal.

Parameters

ParameterType
attemptany
__namedParameters?{ }

Returns

Promise<boolean>


createSecretClipboardGuard()

function createSecretClipboardGuard(hooks): SecretClipboardGuard;

Defined in: lib/clipboard-sync.js:663

Takes a secret the session copied back off the local clipboard.

A password manager marks what it copies so that no clipboard history keeps it, and empties its own clipboard after a while. A page can put no such mark on what it writes, so a secret written here is taken back instead: SECRET_CLIPBOARD_TTL_MS after it landed, or as soon as the session's clipboard moves on, whichever comes first -- and only while the local clipboard still holds it, since anything else there is a copy made since. The check waits a task, so the write of the payload that retracted the secret is issued first; a write issued before the check lands before it, and one issued during it cancels the clear, since either replaces the secret itself.

Only Chromium lets a page read and write the clipboard without a user gesture, and only with the clipboard-read permission granted (asking from a timer would raise the prompt) and the document focused, so an unfocused page takes the secret back when it is focused again. Firefox and WebKit refuse both outside a gesture, and a read inside one raises their paste prompt whenever another application's copy is on the clipboard, so there nothing is watched and the secret stays until something replaces it.

Parameters

ParameterTypeDescription
hooks{ isChromium: boolean; writer: DeferredClipboardWriter; onCleared: () => void; }-
hooks.isChromiumbooleanEngine flag.
hooks.writerDeferredClipboardWriterThe local writer, whose writes settle first.
hooks.onCleared() => voidThe secret was taken back.

Returns

SecretClipboardGuard


createIncomingClipboard()

function createIncomingClipboard(hooks): IncomingClipboard;

Defined in: lib/clipboard-sync.js:787

The server-to-client clipboard, shared by both transports: reassembly, the cache and preview, and the local write.

The local write of a multipart payload is issued the moment the payload is announced, with its bytes still crossing, as a ClipboardItem whose data are Promises. Engines decide whether a write may happen when write() is called -- Chromium wants the document focused, Firefox and WebKit a user activation a few seconds old at most -- and let the data settle long after, while a multi-megabyte image takes seconds to arrive: a write issued only then finds the user already back in the application they copied for, is refused, and lands on their next gesture, one copy behind. Whether the payload repeats what the client already holds is known only once its bytes are digested, so a repeat, a payload that arrived broken, and one a newer payload superseded all withdraw the write by rejecting its data, which leaves the local clipboard as it was. A whole payload in one message is written as soon as it is decoded. Every write goes through writer, which stashes one the engine refuses until the next gesture, and an older write still waiting for its data is withdrawn when a newer one is issued, so a slow conversion can never land an older value over a newer one.

A payload superseded before it landed is dropped whole, its cache update included: the newer one carries the session's clipboard, and a repeat of the dropped content would otherwise read as already held and never land. cacheOnly marks the reply to the connect-time fetch, which fills the cache and preview but never the local clipboard.

A secret payload is text a password manager copied in the session. Its preview reaches the dashboards masked, never as the text, and nothing of it is stored anywhere but this module's memory; written locally, it is watched by createSecretClipboardGuard, which takes it back when its time is up or when any later payload shows the session's clipboard moved on. An empty secret is that retraction without a replacement: the session's clipboard no longer holds the secret, so nothing is written, and the local copy is taken back where it is still there.

Parameters

ParameterTypeDescription
hooks{ worker: { decode: Function; decodeStream: Function; }; clipboardSync: ClipboardSync; writer: DeferredClipboardWriter; toPng: (blob) => Promise<Blob>; canWriteLocal: () => boolean; binaryEnabled: () => boolean; onPreview: (text, secret) => void; onImageWritten: (mime) => void | Promise<any>; onImageWriteFailed: (err) => void; isChromium?: boolean; }-
hooks.worker{ decode: Function; decodeStream: Function; }The clipboard worker bridge.
hooks.worker.decodeFunction-
hooks.worker.decodeStreamFunction-
hooks.clipboardSyncClipboardSyncThe server-clipboard state.
hooks.writerDeferredClipboardWriterThe local writer.
hooks.toPng(blob) => Promise<Blob>Off-thread PNG conversion.
hooks.canWriteLocal() => booleanWhether server content may reach the local clipboard now.
hooks.binaryEnabled() => booleanWhether images are taken.
hooks.onPreview(text, secret) => voidShows server text to the dashboards, a secret masked.
hooks.onImageWritten(mime) => void | Promise<any>An image landed locally; what it returns is awaited before the landing counts as done.
hooks.onImageWriteFailed(err) => voidAn image write failed for good.
hooks.isChromium?booleanEngine flag, for the secret guard.

Returns

IncomingClipboard


armStallTimer()

function armStallTimer(): void;

Defined in: lib/clipboard-sync.js:810

A payload whose chunks stopped arriving is dropped, so its write settles rather than holding every later paste decision on a value that is never coming.

Returns

void


withdraw()

function withdraw(landing, reason): void;

Defined in: lib/clipboard-sync.js:851

Withdraws a write still waiting for its data; the local clipboard keeps its value.

Parameters

ParameterType
landingany
reasonany

Returns

void


issue()

function issue(
   kind, 
   mime, 
   secret
): object;

Defined in: lib/clipboard-sync.js:862

Issues a local write whose data settle later: one Promise per type the item carries, declared now because a ClipboardItem cannot add a type. A secret is handed to the guard once it landed.

Parameters

ParameterType
kindany
mimeany
secretany

Returns

object

parts
parts: object = {};
settled
settled: boolean = false;
withdrawn
withdrawn: boolean = false;
failed
failed: any = null;
localSig
localSig: any = null;

fulfill()

function fulfill(
   landing, 
   kind, 
   content
): void;

Defined in: lib/clipboard-sync.js:900

Hands a landing its data. A conversion still running when a newer write withdraws this one resolves nothing: the part was rejected first.

Parameters

ParameterType
landingany
kindany
contentany

Returns

void


land()

function land(t, decoded): void;

Defined in: lib/clipboard-sync.js:926

Caches a complete payload, shows its preview, and lands it locally through the write already issued for it or a new one.

Parameters

ParameterType
tany
decodedany

Returns

void


writeText()

function writeText(text, secret): Promise<boolean>;

Defined in: lib/clipboard-sync.js:979

Writes text locally through the writer, a secret into the guard's care.

Parameters

ParameterType
textany
secretany

Returns

Promise<boolean>


open()

function open(
   mime, 
   cacheOnly, 
   secret
): object;

Defined in: lib/clipboard-sync.js:990

Opens a payload, superseding whatever was still arriving.

Parameters

ParameterType
mimeany
cacheOnlyany
secretany

Returns

object

kind
kind: string;
mime
mime: any;
cacheOnly
cacheOnly: any;
secret
secret: boolean;
gen
gen: number = ++generation;
landing
landing: any = null;

clipboardPreviewMessage()

function clipboardPreviewMessage(text, secret?): object;

Defined in: lib/clipboard-sync.js:1087

The clipboardContentUpdate message carrying server clipboard text to the dashboards.

A multi-MB payload structured-clones through postMessage and lands in a controlled textarea, freezing the page, while the UI only needs a bounded preview. The truncated flag tells the dashboard to render it read-only so a blur cannot echo the cut-down text back over the real server clipboard. A secret travels as the secret flag alone, never as its text or length: the dashboards show it masked, read-only for the same reason, with a button that posts clipboardCopySecret for the core to write it locally.

Parameters

ParameterTypeDefault valueDescription
textstringundefinedThe server clipboard text.
secret?booleanfalseWhether the text is a secret.

Returns

object

type
type: string;
text
text: string;
truncated
truncated: boolean;
totalLength
totalLength: number;
secret
secret: boolean;

sameLines()

function sameLines(text): string;

Defined in: lib/clipboard-sync.js:1163

Text as the session and the browser both mean it: line ends are LF. Chromium on Windows keeps plain text with CRLF line ends whatever was written, so the session's own text reads back from the local clipboard with its line ends changed, which must not read as a copy.

Parameters

ParameterTypeDescription
textstring-

Returns

string


createClipboardSync()

function createClipboardSync(__namedParameters): object;

Defined in: lib/clipboard-sync.js:1167

Parameters

ParameterType
__namedParameters{ sendRequest: any; digestBytes: any; isChromium?: boolean; canRead?: () => boolean; }
__namedParameters.sendRequestany
__namedParameters.digestBytesany
__namedParameters.isChromium?boolean
__namedParameters.canRead?() => boolean

Returns

sig
sig: (data, mime) => string;
Parameters
ParameterType
dataany
mimeany
Returns

string

shouldSend
shouldSend: (data, mime) => boolean;

Change-only gate: true while this content and mime differ from the last synced value. Read-only: the caller marks the content synced through markSynced only after the transfer completes, so a failed transfer never permanently suppresses re-sending the same content. The legacy compare suppresses echoes of content whose receive-side signature was stored without bytes.

Parameters
ParameterType
dataany
mimeany
Returns

boolean

markSynced
markSynced: (data, mime) => void;

Records content as synced; called on transfer success.

Parameters
ParameterType
dataany
mimeany
Returns

void

localSig
localSig: (data, mime) => Promise<string>;

Signature of content read from the local clipboard, in the form shouldSend compares. Bytes are digested by the worker where the caller supplied one, from a copy, since they are still to be sent.

Parameters
ParameterType
dataany
mimeany
Returns

Promise<string>

noteLocal
noteLocal: (s) => boolean;

Records what the local clipboard holds now, from a read or from a write made here (null when its form there is unknown).

Parameters
ParameterType
sany
Returns

boolean

Whether that differs from what it held last time; the first look after a push the user asked for finds what the clipboard held before it, which is no change.

noteExplicit
noteExplicit: () => void;

A push the user asked for (an upload, the clipboard box) made the session's clipboard newer than whatever the local one holds, seen here or not: an engine that reads the local clipboard only as a paste delivers it has never seen it.

Returns

void

forget
forget: () => void;

After this page emptied the local clipboard (a secret taken back), the session's next copy of the same content has to land again, and whatever the user copies next is a change.

Returns

void

forgetLocal
forgetLocal: (s) => void;

A push of the local clipboard that never left (no connection, or it dropped mid-send) leaves the content still news to the session: the next read finds it a change again. A newer reading, or a push the user asked for since, stands.

Parameters
ParameterType
sany
Returns

void

resolveServer
resolveServer: (text, blob, mime, bytes) => void;

Caches fresh server data and settles pending requests through the one-behind guard. bytes, when the receive path has them, make the stored signature content-hashed so it matches what shouldSend computes for the same data.

Parameters
ParameterType
textany
blobany
mimeany
bytesany
Returns

void

captureLocalImageSig
captureLocalImageSig: () => Promise<void>;

After a server image is written to the local clipboard, records the browser's re-encoded representation so the next focus read is recognized as the same content instead of echoed back. Needs clipboard read permission and focus and is silently skipped otherwise; the worst case is one redundant round trip, never a loop. The capture is anchored to the synced signature at entry: a sync in either direction landing mid-read makes it stale, and storing it would suppress a legitimate later copy.

Returns

Promise<void>

request
request: (wantBinary) => Promise<string | Blob>;

Requests the server clipboard and resolves with the next fresh value.

After two seconds the request settles so the ClipboardItem promise, and the browser's transient-activation window, can never hang: with a cached value that differs from the baseline recorded at request time it resolves, otherwise it rejects, since resolving with the baseline-equal cache would settle the copy with stale content exactly when the session-start cache is empty or stale.

Parameters
ParameterTypeDescription
wantBinarybooleanWhether an image is wanted rather than text.
Returns

Promise<string | Blob>

copyViaExecCommand
copyViaExecCommand: (textPromise) => Promise<void>;

Last-resort copy for browsers that reject navigator.clipboard.write (older Firefox and Safari): execCommand('copy') from a hidden textarea. Awaiting the promise first can outlive the Ctrl/Cmd+C transient activation, hence last resort. A rejected request or an empty value writes nothing: either would clobber the user's local clipboard with pre-copy content.

Parameters
ParameterTypeDescription
textPromisePromise<string>The pending server text.
Returns

Promise<void>

lastText
Get Signature
get lastText(): string;
Returns

string

echoes
echoes: (text) => boolean;

Whether text read from the local clipboard is the value last synced, come back in another form: what the session sent, or what this page sent it, so sending it would only take the session's clipboard from its owner (a file manager's cut is the owner's alone).

Parameters
ParameterTypeDescription
textstringThe read's plain text.
Returns

boolean

lastBlob
Get Signature
get lastBlob(): any;
Returns

any

lastMime
Get Signature
get lastMime(): string;
Returns

string


sigOf()

function sigOf(data, mime): object;

Defined in: lib/clipboard-sync.js:1197

Both signature forms of a value. Text and byte-backed values are content-hashed so two distinct payloads of equal size still differ; a bare Blob, whose bytes are not in hand, gets the size-only legacy form, which also rides along with hashed binary signatures so the two can be cross-matched.

Parameters

ParameterType
dataany
mimeany

Returns

object

full
full: string;
legacy
legacy: string;

shouldSend()

function shouldSend(data, mime): boolean;

Defined in: lib/clipboard-sync.js:1233

Change-only gate: true while this content and mime differ from the last synced value. Read-only: the caller marks the content synced through markSynced only after the transfer completes, so a failed transfer never permanently suppresses re-sending the same content. The legacy compare suppresses echoes of content whose receive-side signature was stored without bytes.

Parameters

ParameterType
dataany
mimeany

Returns

boolean


markSynced()

function markSynced(data, mime): void;

Defined in: lib/clipboard-sync.js:1240

Records content as synced; called on transfer success.

Parameters

ParameterType
dataany
mimeany

Returns

void


echoes()

function echoes(text): boolean;

Defined in: lib/clipboard-sync.js:1251

Whether text read from the local clipboard is the value last synced, come back in another form: what the session sent, or what this page sent it, so sending it would only take the session's clipboard from its owner (a file manager's cut is the owner's alone).

Parameters

ParameterTypeDescription
textstringThe read's plain text.

Returns

boolean


localSig()

function localSig(data, mime): Promise<string>;

Defined in: lib/clipboard-sync.js:1260

Signature of content read from the local clipboard, in the form shouldSend compares. Bytes are digested by the worker where the caller supplied one, from a copy, since they are still to be sent.

Parameters

ParameterType
dataany
mimeany

Returns

Promise<string>


noteLocal()

function noteLocal(s): boolean;

Defined in: lib/clipboard-sync.js:1272

Records what the local clipboard holds now, from a read or from a write made here (null when its form there is unknown).

Parameters

ParameterType
sany

Returns

boolean

Whether that differs from what it held last time; the first look after a push the user asked for finds what the clipboard held before it, which is no change.


noteExplicit()

function noteExplicit(): void;

Defined in: lib/clipboard-sync.js:1284

A push the user asked for (an upload, the clipboard box) made the session's clipboard newer than whatever the local one holds, seen here or not: an engine that reads the local clipboard only as a paste delivers it has never seen it.

Returns

void


forget()

function forget(): void;

Defined in: lib/clipboard-sync.js:1293

After this page emptied the local clipboard (a secret taken back), the session's next copy of the same content has to land again, and whatever the user copies next is a change.

Returns

void


forgetLocal()

function forgetLocal(s): void;

Defined in: lib/clipboard-sync.js:1304

A push of the local clipboard that never left (no connection, or it dropped mid-send) leaves the content still news to the session: the next read finds it a change again. A newer reading, or a push the user asked for since, stands.

Parameters

ParameterType
sany

Returns

void


resolveServer()

function resolveServer(
   text, 
   blob, 
   mime, 
   bytes
): void;

Defined in: lib/clipboard-sync.js:1314

Caches fresh server data and settles pending requests through the one-behind guard. bytes, when the receive path has them, make the stored signature content-hashed so it matches what shouldSend computes for the same data.

Parameters

ParameterType
textany
blobany
mimeany
bytesany

Returns

void


captureLocalImageSig()

function captureLocalImageSig(): Promise<void>;

Defined in: lib/clipboard-sync.js:1345

After a server image is written to the local clipboard, records the browser's re-encoded representation so the next focus read is recognized as the same content instead of echoed back. Needs clipboard read permission and focus and is silently skipped otherwise; the worst case is one redundant round trip, never a loop. The capture is anchored to the synced signature at entry: a sync in either direction landing mid-read makes it stale, and storing it would suppress a legitimate later copy.

Returns

Promise<void>


request()

function request(wantBinary): Promise<string | Blob>;

Defined in: lib/clipboard-sync.js:1382

Requests the server clipboard and resolves with the next fresh value.

After two seconds the request settles so the ClipboardItem promise, and the browser's transient-activation window, can never hang: with a cached value that differs from the baseline recorded at request time it resolves, otherwise it rejects, since resolving with the baseline-equal cache would settle the copy with stale content exactly when the session-start cache is empty or stale.

Parameters

ParameterTypeDescription
wantBinarybooleanWhether an image is wanted rather than text.

Returns

Promise<string | Blob>


copyViaExecCommand()

function copyViaExecCommand(textPromise): Promise<void>;

Defined in: lib/clipboard-sync.js:1417

Last-resort copy for browsers that reject navigator.clipboard.write (older Firefox and Safari): execCommand('copy') from a hidden textarea. Awaiting the promise first can outlive the Ctrl/Cmd+C transient activation, hence last resort. A rejected request or an empty value writes nothing: either would clobber the user's local clipboard with pre-copy content.

Parameters

ParameterTypeDescription
textPromisePromise<string>The pending server text.

Returns

Promise<void>


createClipboardGestures()

function createClipboardGestures(hooks): object;

Defined in: lib/clipboard-sync.js:1515

Keyboard and paste gesture wiring for clipboard sync.

Owns the three window-level pieces around the per-transport read and send functions:

  • Paste-ordering hold: a Ctrl/Cmd+V arriving while the local clipboard is still being read or sent would depart the ordered channel before the clipboard content and paste the previous value on the server. The chord's key events are swallowed, held until the send flushes (bounded), then replayed in order for the input stack; outside Chromium every chord is held for the send its own paste event starts. In Chromium the chord starts a read of its own and is held for it, since the clipboard can change without the window losing focus: a copy in another tab or from a tool outside the page leaves the focus read's value stale.
  • Non-Chromium Ctrl/Cmd+C: Safari and Firefox reject navigator.clipboard from focus and message handlers, which have no transient activation, so the server clipboard is written inside the copy gesture through a ClipboardItem whose blob is a Promise, with execCommand('copy') as last resort.
  • Non-Chromium paste-to-server: driven by the paste event's synchronous clipboardData. There is deliberately no Ctrl/Cmd+V navigator.clipboard read: WebKit rejects it from keydown, Firefox re-raises its paste prompt, and it would double-send next to the paste event. While a session value is still on its way to the local clipboard the local one is older than the session's, so the paste sends nothing and the chord pastes the session's.

Gestures in page form fields (the settings UI) are left alone; the stream's overlay input is exempt. Consumed gestures are never preventDefaulted outside the Chromium hold: the chord must still reach the remote session, and outside Chromium its default action is the paste event itself. That paste event is canceled once the stream takes it, so its text is not also inserted into the stream's input.

Parameters

ParameterTypeDescription
hooks{ isChromium: boolean; clipboardSync: ClipboardSync; sendClipboardData: (data, mime?) => Promise<void>; canSync: () => boolean; canRead: () => boolean; canWrite: () => boolean; binaryEnabled: () => boolean; getSendInFlight: () => Promise<any>; getDeferredWriteLanding?: () => Promise<any>; hasPendingServerWrite?: () => boolean; readLocalClipboard?: () => Promise<void>; }-
hooks.isChromiumbooleanEngine flag.
hooks.clipboardSyncClipboardSyncThe server-clipboard state.
hooks.sendClipboardData(data, mime?) => Promise<void>Transport send.
hooks.canSync() => booleanClipboard sync enabled.
hooks.canRead() => booleanLocal-to-server direction enabled.
hooks.canWrite() => booleanServer-to-local direction enabled.
hooks.binaryEnabled() => booleanWhether images are sent.
hooks.getSendInFlight() => Promise<any>The local sender's pending send.
hooks.getDeferredWriteLanding?() => Promise<any>The deferred writer's write whose data are complete, still landing.
hooks.hasPendingServerWrite?() => booleanWhether a session value has yet to land in the local clipboard.
hooks.readLocalClipboard?() => Promise<void>Chromium's read and send of the local clipboard, which a paste chord starts.

Returns

object

Listener registration.

wire
wire: () => void;
Returns

void

unwire
unwire: () => void;
Returns

void


dropHeldPasteKeydowns()

function dropHeldPasteKeydowns(): void;

Defined in: lib/clipboard-sync.js:1565

The in-flight transfer failed or never settled: injecting the held V now would paste stale content, so the held keydowns are dropped. The swallowed keyups (V and the chord's modifiers) are still replayed, as losing a modifier keyup would leave it stuck server-side.

Returns

void


holdPasteWhileClipboardInFlight()

function holdPasteWhileClipboardInFlight(ev): void;

Defined in: lib/clipboard-sync.js:1598

Capture-phase key listener implementing the paste-ordering hold.

A paste chord is held while a send is in flight or a server-to-client local-clipboard write is still landing, since the paste would otherwise read the old value; any KeyV event is held while a replay is queued, so its keyup cannot overtake the held keydown, and so are the chord's modifier keyups, since a Ctrl keyup overtaking the replayed V would break the chord server-side and type a literal v. The hold waits for the current read/send and deferred write, then re-checks, as a follow-on transfer may have started meanwhile (the deferred write flushed by this very keydown); replay happens only once nothing is pending, and on failure or an expired bound the paste is dropped rather than injected with stale content.

Outside Chromium the local clipboard reaches the page only through the chord's own paste event, which the engine dispatches once this keydown has been, so every chord is held for it: its V would otherwise reach the session ahead of what it pastes, and the first paste of every copy would paste the one before. There the keydown keeps its default action, since that action is the paste.

In Chromium the chord's keydown starts the read and send itself and is held for it, the counterpart of the paste event elsewhere.

Parameters

ParameterTypeDescription
evKeyboardEvent-

Returns

void


onCopyKeydown()

function onCopyKeydown(event): void;

Defined in: lib/clipboard-sync.js:1662

Non-Chromium Ctrl/Cmd+C: writes the server clipboard inside the gesture.

Only text/plain is advertised: a Ctrl/Cmd+C cannot synchronously know whether the server's current clipboard is an image, and a stale cached MIME type would build a malformed ClipboardItem. Server images are delivered by the push handler instead. Autorepeat is ignored so it cannot spam REQUEST_CLIPBOARD.

Parameters

ParameterTypeDescription
eventKeyboardEvent-

Returns

void


onPaste()

function onPaste(event): void;

Defined in: lib/clipboard-sync.js:1698

Non-Chromium paste-to-server from the event's synchronous clipboard data, preferring an image when binary clipboard is on and the payload carries one. Only content the page has not seen on the local clipboard is sent: what it has seen there is older than whatever the session took since, an upload or a copy made in the session.

Parameters

ParameterTypeDescription
eventClipboardEvent-

Returns

void


wire()

function wire(): void;

Defined in: lib/clipboard-sync.js:1733

Registers the listeners; called before input attaches so the hold runs first.

Returns

void


unwire()

function unwire(): void;

Defined in: lib/clipboard-sync.js:1743

Removes the listeners wire registered.

Returns

void

On this page

InterfacesMultipartClipboardStatePropertiesbeginParametersReturnspushParametersReturnsfinishReturnsresetReturnsinProgressmimeTypetotalSizereceivedSizeTaggedClipboardFetchPropertiesarmReturnsarmLegacyWindowParametersReturnsconsumeReturnsLocalClipboardSenderPropertiesreadAndSendReturnssendExplicitParametersReturnsmaybeInitialReturnsgetSendInFlightReturnsDeferredClipboardWriterPropertieswriteParametersReturnsflushReturnsgetInFlightReturnsgetLandingReturnshasPendingReturnsissuedReturnsSecretClipboardGuardPropertieslandedParametersReturnsholdsParametersReturnsretractReturnsIncomingClipboardPropertiesbeginParametersReturnspushParametersReturnsfinishReturnssingleParametersReturnsmarkSecretReturnscopySecretReturnsresetReturnsClipboardSyncPropertiessigParametersReturnsshouldSendParametersReturnsmarkSyncedParametersReturnslocalSigParametersReturnsnoteLocalParametersReturnsnoteExplicitReturnsforgetReturnsforgetLocalParametersReturnsechoesParametersReturnsresolveServerParametersReturnscaptureLocalImageSigReturnsrequestParametersReturnscopyViaExecCommandParametersReturnslastTextlastBloblastMimeType AliasesLocalClipboardContentType ParametersVariablesCLIPBOARD_FLAVOURS_MIMESECRET_CLIPBOARD_TTL_MSCLIPBOARD_PREVIEW_LIMITFunctionsdigestedPayload()ParametersReturnsbyteLengthhashreencodeBlobAsPng()ParametersReturnsThrowslocalClipboardBlocker()ReturnspackClipboardFlavours()ParametersReturnsunpackClipboardFlavours()ParametersReturnshtmltexttextOfMarkup()ParametersReturnsreadLocalClipboard()ParametersReturnsThrowscreateMultipartClipboardState()ParametersReturnscreateTaggedClipboardFetch()ReturnscreateLocalClipboardSender()ParametersReturnsexplicitHasPrecedence()ReturnsasSendInFlight()ParametersReturnsreadAndSend()ReturnssendExplicit()ParametersReturnscreateDeferredClipboardWriter()ReturnsattemptOnce()ParametersReturnswrite()ParametersReturnscreateSecretClipboardGuard()ParametersReturnscreateIncomingClipboard()ParametersReturnsarmStallTimer()Returnswithdraw()ParametersReturnsissue()ParametersReturnspartssettledwithdrawnfailedlocalSigfulfill()ParametersReturnsland()ParametersReturnswriteText()ParametersReturnsopen()ParametersReturnskindmimecacheOnlysecretgenlandingclipboardPreviewMessage()ParametersReturnstypetexttruncatedtotalLengthsecretsameLines()ParametersReturnscreateClipboardSync()ParametersReturnssigParametersReturnsshouldSendParametersReturnsmarkSyncedParametersReturnslocalSigParametersReturnsnoteLocalParametersReturnsnoteExplicitReturnsforgetReturnsforgetLocalParametersReturnsresolveServerParametersReturnscaptureLocalImageSigReturnsrequestParametersReturnscopyViaExecCommandParametersReturnslastTextGet SignatureReturnsechoesParametersReturnslastBlobGet SignatureReturnslastMimeGet SignatureReturnssigOf()ParametersReturnsfulllegacyshouldSend()ParametersReturnsmarkSynced()ParametersReturnsechoes()ParametersReturnslocalSig()ParametersReturnsnoteLocal()ParametersReturnsnoteExplicit()Returnsforget()ReturnsforgetLocal()ParametersReturnsresolveServer()ParametersReturnscaptureLocalImageSig()Returnsrequest()ParametersReturnscopyViaExecCommand()ParametersReturnscreateClipboardGestures()ParametersReturnswireReturnsunwireReturnsdropHeldPasteKeydowns()ReturnsholdPasteWhileClipboardInFlight()ParametersReturnsonCopyKeydown()ParametersReturnsonPaste()ParametersReturnswire()Returnsunwire()Returns
Edit on GitHub