embed: allow embeds like YouTube to link back to its site (#3609)
Fixes https://github.com/tldraw/tldraw/issues/3593 (some drive-by spelling/grammar cleanup) ### Change Type <!-- ❗ Please select a 'Scope' label ❗️ --> - [x] `sdk` — Changes the tldraw SDK - [ ] `dotcom` — Changes the tldraw.com web app - [ ] `docs` — Changes to the documentation, examples, or templates. - [ ] `vs code` — Changes to the vscode plugin - [ ] `internal` — Does not affect user-facing stuff <!-- ❗ Please select a 'Type' label ❗️ --> - [x] `bugfix` — Bug fix - [ ] `feature` — New feature - [ ] `improvement` — Improving existing features - [ ] `chore` — Updating dependencies, other boring stuff - [ ] `galaxy brain` — Architectural changes - [ ] `tests` — Changes to any test code - [ ] `tools` — Changes to infrastructure, CI, internal scripts, debugging tools, etc. - [ ] `dunno` — I don't know ### Release Notes - Embeds: fix being able to click on links that go back to the embed's site (e.g. YouTube) --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
b8afbb4c43
commit
487addd2e8
2 changed files with 35 additions and 15 deletions
|
@ -256,6 +256,9 @@ export const EMBED_DEFINITIONS: readonly [{
|
||||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||||
readonly height: 500;
|
readonly height: 500;
|
||||||
readonly hostnames: readonly ["google.*"];
|
readonly hostnames: readonly ["google.*"];
|
||||||
|
readonly overridePermissions: {
|
||||||
|
readonly 'allow-presentation': true;
|
||||||
|
};
|
||||||
readonly title: "Google Maps";
|
readonly title: "Google Maps";
|
||||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||||
readonly type: "google_maps";
|
readonly type: "google_maps";
|
||||||
|
@ -309,6 +312,7 @@ export const EMBED_DEFINITIONS: readonly [{
|
||||||
readonly hostnames: readonly ["*.youtube.com", "youtube.com", "youtu.be"];
|
readonly hostnames: readonly ["*.youtube.com", "youtube.com", "youtu.be"];
|
||||||
readonly isAspectRatioLocked: true;
|
readonly isAspectRatioLocked: true;
|
||||||
readonly overridePermissions: {
|
readonly overridePermissions: {
|
||||||
|
readonly 'allow-popups-to-escape-sandbox': true;
|
||||||
readonly 'allow-presentation': true;
|
readonly 'allow-presentation': true;
|
||||||
};
|
};
|
||||||
readonly title: "YouTube";
|
readonly title: "YouTube";
|
||||||
|
@ -323,6 +327,9 @@ export const EMBED_DEFINITIONS: readonly [{
|
||||||
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
|
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
|
||||||
readonly minHeight: 360;
|
readonly minHeight: 360;
|
||||||
readonly minWidth: 460;
|
readonly minWidth: 460;
|
||||||
|
readonly overridePermissions: {
|
||||||
|
readonly 'allow-popups-to-escape-sandbox': true;
|
||||||
|
};
|
||||||
readonly title: "Google Calendar";
|
readonly title: "Google Calendar";
|
||||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||||
readonly type: "google_calendar";
|
readonly type: "google_calendar";
|
||||||
|
@ -334,6 +341,9 @@ export const EMBED_DEFINITIONS: readonly [{
|
||||||
readonly hostnames: readonly ["docs.google.*"];
|
readonly hostnames: readonly ["docs.google.*"];
|
||||||
readonly minHeight: 360;
|
readonly minHeight: 360;
|
||||||
readonly minWidth: 460;
|
readonly minWidth: 460;
|
||||||
|
readonly overridePermissions: {
|
||||||
|
readonly 'allow-popups-to-escape-sandbox': true;
|
||||||
|
};
|
||||||
readonly title: "Google Slides";
|
readonly title: "Google Slides";
|
||||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||||
readonly type: "google_slides";
|
readonly type: "google_slides";
|
||||||
|
|
|
@ -83,6 +83,9 @@ export const EMBED_DEFINITIONS = [
|
||||||
width: 720,
|
width: 720,
|
||||||
height: 500,
|
height: 500,
|
||||||
doesResize: true,
|
doesResize: true,
|
||||||
|
overridePermissions: {
|
||||||
|
'allow-presentation': true,
|
||||||
|
},
|
||||||
toEmbedUrl: (url) => {
|
toEmbedUrl: (url) => {
|
||||||
if (url.includes('/maps/')) {
|
if (url.includes('/maps/')) {
|
||||||
const match = url.match(/@(.*),(.*),(.*)z/)
|
const match = url.match(/@(.*),(.*),(.*)z/)
|
||||||
|
@ -123,8 +126,8 @@ export const EMBED_DEFINITIONS = [
|
||||||
doesResize: true,
|
doesResize: true,
|
||||||
toEmbedUrl: (url) => {
|
toEmbedUrl: (url) => {
|
||||||
const urlObj = safeParseUrl(url)
|
const urlObj = safeParseUrl(url)
|
||||||
// e.g. extract "steveruizok.mathFact" from https://www.val.town/v/steveruizok.mathFact
|
// e.g. extract "steveruizok/mathFact" from https://www.val.town/v/steveruizok/mathFact
|
||||||
const matches = urlObj && urlObj.pathname.match(/\/v\/([^/]+)\/?/)
|
const matches = urlObj && urlObj.pathname.match(/\/v\/(.+)\/?/)
|
||||||
if (matches) {
|
if (matches) {
|
||||||
return `https://www.val.town/embed/${matches[1]}`
|
return `https://www.val.town/embed/${matches[1]}`
|
||||||
}
|
}
|
||||||
|
@ -132,8 +135,8 @@ export const EMBED_DEFINITIONS = [
|
||||||
},
|
},
|
||||||
fromEmbedUrl: (url) => {
|
fromEmbedUrl: (url) => {
|
||||||
const urlObj = safeParseUrl(url)
|
const urlObj = safeParseUrl(url)
|
||||||
// e.g. extract "steveruizok.mathFact" from https://www.val.town/v/steveruizok.mathFact
|
// e.g. extract "steveruizok/mathFact" from https://www.val.town/v/steveruizok/mathFact
|
||||||
const matches = urlObj && urlObj.pathname.match(/\/embed\/([^/]+)\/?/)
|
const matches = urlObj && urlObj.pathname.match(/\/embed\/(.+)\/?/)
|
||||||
if (matches) {
|
if (matches) {
|
||||||
return `https://www.val.town/v/${matches[1]}`
|
return `https://www.val.town/v/${matches[1]}`
|
||||||
}
|
}
|
||||||
|
@ -229,6 +232,7 @@ export const EMBED_DEFINITIONS = [
|
||||||
doesResize: true,
|
doesResize: true,
|
||||||
overridePermissions: {
|
overridePermissions: {
|
||||||
'allow-presentation': true,
|
'allow-presentation': true,
|
||||||
|
'allow-popups-to-escape-sandbox': true,
|
||||||
},
|
},
|
||||||
isAspectRatioLocked: true,
|
isAspectRatioLocked: true,
|
||||||
toEmbedUrl: (url) => {
|
toEmbedUrl: (url) => {
|
||||||
|
@ -272,6 +276,9 @@ export const EMBED_DEFINITIONS = [
|
||||||
minHeight: 360,
|
minHeight: 360,
|
||||||
doesResize: true,
|
doesResize: true,
|
||||||
instructionLink: 'https://support.google.com/calendar/answer/41207?hl=en',
|
instructionLink: 'https://support.google.com/calendar/answer/41207?hl=en',
|
||||||
|
overridePermissions: {
|
||||||
|
'allow-popups-to-escape-sandbox': true,
|
||||||
|
},
|
||||||
toEmbedUrl: (url) => {
|
toEmbedUrl: (url) => {
|
||||||
const urlObj = safeParseUrl(url)
|
const urlObj = safeParseUrl(url)
|
||||||
const cidQs = urlObj?.searchParams.get('cid')
|
const cidQs = urlObj?.searchParams.get('cid')
|
||||||
|
@ -313,6 +320,9 @@ export const EMBED_DEFINITIONS = [
|
||||||
minWidth: 460,
|
minWidth: 460,
|
||||||
minHeight: 360,
|
minHeight: 360,
|
||||||
doesResize: true,
|
doesResize: true,
|
||||||
|
overridePermissions: {
|
||||||
|
'allow-popups-to-escape-sandbox': true,
|
||||||
|
},
|
||||||
toEmbedUrl: (url) => {
|
toEmbedUrl: (url) => {
|
||||||
const urlObj = safeParseUrl(url)
|
const urlObj = safeParseUrl(url)
|
||||||
|
|
||||||
|
@ -571,37 +581,37 @@ export const embedShapePermissionDefaults = {
|
||||||
// Disabled permissions
|
// Disabled permissions
|
||||||
// ========================================================================================
|
// ========================================================================================
|
||||||
// [MDN] Experimental: Allows for downloads to occur without a gesture from the user.
|
// [MDN] Experimental: Allows for downloads to occur without a gesture from the user.
|
||||||
// [REASON] Disabled because otherwise the <iframe/> trick the user on behalf of us to performing an action
|
// [REASON] Disabled because otherwise the <iframe/> can trick the user on behalf of us to perform an action.
|
||||||
'allow-downloads-without-user-activation': false,
|
'allow-downloads-without-user-activation': false,
|
||||||
// [MDN] Allows for downloads to occur with a gesture from the user.
|
// [MDN] Allows for downloads to occur with a gesture from the user.
|
||||||
// [REASON] Disabled because otherwise the <iframe/> trick the user on behalf of us to performing an action
|
// [REASON] Disabled because otherwise the <iframe/> can trick the user on behalf of us to perform an action.
|
||||||
'allow-downloads': false,
|
'allow-downloads': false,
|
||||||
// [MDN] Lets the resource open modal windows.
|
// [MDN] Lets the resource open modal windows.
|
||||||
// [REASON] The <iframe/> could 'window.prompt("Enter your tldraw password")'
|
// [REASON] The <iframe/> could 'window.prompt("Enter your tldraw password")'.
|
||||||
'allow-modals': false,
|
'allow-modals': false,
|
||||||
// [MDN] Lets the resource lock the screen orientation.
|
// [MDN] Lets the resource lock the screen orientation.
|
||||||
// [REASON] Would interfer with tldraw interface
|
// [REASON] Would interfere with the tldraw interface.
|
||||||
'allow-orientation-lock': false,
|
'allow-orientation-lock': false,
|
||||||
// [MDN] Lets the resource use the Pointer Lock API.
|
// [MDN] Lets the resource use the Pointer Lock API.
|
||||||
// [REASON] Maybe we should allow this for games embeds (scratch/codepen/codesandbox)
|
// [REASON] Maybe we should allow this for games embeds (scratch/codepen/codesandbox).
|
||||||
'allow-pointer-lock': false,
|
'allow-pointer-lock': false,
|
||||||
// [MDN] Allows popups (such as window.open(), target="_blank", or showModalDialog()). If this keyword is not used, the popup will silently fail to open.
|
// [MDN] Allows popups (such as window.open(), target="_blank", or showModalDialog()). If this keyword is not used, the popup will silently fail to open.
|
||||||
// [REASON] We shouldn't allow popups as a embed could pretend to be us by opening a mocked version of tldraw. This is very unobvious when it is performed as an action within out app
|
// [REASON] We want to allow embeds to link back to their original sites (e.g. YouTube).
|
||||||
'allow-popups': true,
|
'allow-popups': true,
|
||||||
// [MDN] Lets the sandboxed document open new windows without those windows inheriting the sandboxing. For example, this can safely sandbox an advertisement without forcing the same restrictions upon the page the ad links to.
|
// [MDN] Lets the sandboxed document open new windows without those windows inheriting the sandboxing. For example, this can safely sandbox an advertisement without forcing the same restrictions upon the page the ad links to.
|
||||||
// [REASON] We're alread disabling popups.
|
// [REASON] We shouldn't allow popups as a embed could pretend to be us by opening a mocked version of tldraw. This is very unobvious when it is performed as an action within our app.
|
||||||
'allow-popups-to-escape-sandbox': false,
|
'allow-popups-to-escape-sandbox': false,
|
||||||
// [MDN] Lets the resource start a presentation session.
|
// [MDN] Lets the resource start a presentation session.
|
||||||
// [REASON] Prevents embed from navigating away from tldraw and pretending to be us
|
// [REASON] Prevents embed from navigating away from tldraw and pretending to be us.
|
||||||
'allow-presentation': false,
|
'allow-presentation': false,
|
||||||
// [MDN] Experimental: Lets the resource request access to the parent's storage capabilities with the Storage Access API.
|
// [MDN] Experimental: Lets the resource request access to the parent's storage capabilities with the Storage Access API.
|
||||||
// [REASON] We don't want anyone else to access our storage
|
// [REASON] We don't want anyone else to access our storage.
|
||||||
'allow-storage-access-by-user-activation': false,
|
'allow-storage-access-by-user-activation': false,
|
||||||
// [MDN] Lets the resource navigate the top-level browsing context (the one named _top).
|
// [MDN] Lets the resource navigate the top-level browsing context (the one named _top).
|
||||||
// [REASON] Prevents embed from navigating away from tldraw and pretending to be us
|
// [REASON] Prevents embed from navigating away from tldraw and pretending to be us.
|
||||||
'allow-top-navigation': false,
|
'allow-top-navigation': false,
|
||||||
// [MDN] Lets the resource navigate the top-level browsing context, but only if initiated by a user gesture.
|
// [MDN] Lets the resource navigate the top-level browsing context, but only if initiated by a user gesture.
|
||||||
// [REASON] Prevents embed from navigating away from tldraw and pretending to be us
|
// [REASON] Prevents embed from navigating away from tldraw and pretending to be us.
|
||||||
'allow-top-navigation-by-user-activation': false,
|
'allow-top-navigation-by-user-activation': false,
|
||||||
// ========================================================================================
|
// ========================================================================================
|
||||||
// Enabled permissions
|
// Enabled permissions
|
||||||
|
|
Loading…
Reference in a new issue