-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
POC - adding messaging proxy #869
base: main
Are you sure you want to change the base?
Conversation
Current dependencies on/for this PR:
This stack of pull requests is managed by Graphite. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what web applications, or special pages would import
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is virtually identical to the Android implementation. I didn't want to cause confusion in the POC with any re-factors though. If we come to agreement on the direction we should probably transition the Android implementation to use this
setupIncomingListener: (dispatch) => { | ||
globalThis.addEventListener('message', (evt) => { | ||
if (evt.origin !== globalThis.location.origin) { | ||
console.warn('ignoring non-matching origin') | ||
return | ||
} | ||
if (!evt.data || !('messageProxyResponse' in evt.data)) { | ||
return | ||
} | ||
dispatch(evt.data.messageProxyResponse) | ||
}) | ||
}, | ||
send: (msg) => { | ||
globalThis.postMessage({ messageProxy: msg }, globalThis.location.origin) | ||
}, | ||
setupSubscription: (msg) => { | ||
globalThis.postMessage({ subscriptionProxy: msg }, globalThis.location.origin) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are the 3 side-effecting things that would occur in the same context as the application's JS (ie: none-isolated)
if (opts.injectName === 'windows') { | ||
const opts = new WindowsMessagingConfig({ | ||
methods: { | ||
// @ts-expect-error - not in @types/chrome | ||
postMessage: window.chrome.webview.postMessage, | ||
// @ts-expect-error - not in @types/chrome | ||
addEventListener: window.chrome.webview.addEventListener, | ||
// @ts-expect-error - not in @types/chrome | ||
removeEventListener: window.chrome.webview.removeEventListener | ||
} | ||
}) | ||
const messaging = new Messaging(messageContext, opts) | ||
return new DuckPlayerPageMessages(messaging) | ||
} else if (opts.injectName === 'apple') { | ||
const opts = new WebkitMessagingConfig({ | ||
hasModernWebkitAPI: true, | ||
secret: '', | ||
webkitMessageHandlerNames: ['specialPages'] | ||
}) | ||
const messaging = new Messaging(messageContext, opts) | ||
return new DuckPlayerPageMessages(messaging) | ||
} else if (opts.injectName === 'integration') { | ||
const config = new TestTransportConfig({ | ||
notify (msg) { | ||
console.log(msg) | ||
}, | ||
request: (msg) => { | ||
console.log(msg) | ||
if (msg.method === 'getUserValues') { | ||
return Promise.resolve(new UserValues({ | ||
overlayInteracted: false, | ||
privatePlayerMode: { alwaysAsk: {} } | ||
})) | ||
} | ||
return Promise.resolve(null) | ||
}, | ||
subscribe (msg) { | ||
console.log(msg) | ||
return () => { | ||
console.log('teardown') | ||
} | ||
} | ||
}) | ||
const messaging = new Messaging(messageContext, config) | ||
return new DuckPlayerPageMessages(messaging) | ||
} | ||
throw new Error('unreachable - platform not supported') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥳 this is the kind of wins we get - since the proxy is sat inside C-S-S the platform-specific parts are already in place.
init (args) { | ||
const thisContext = this._createMessagingContext() | ||
|
||
for (const { origin, feature } of args.messageProxies) { | ||
if (!matchHostname(globalThis.location.hostname, origin)) { | ||
continue | ||
} | ||
const nextMessagingContext = { ...thisContext, featureName: feature } | ||
const messaging = new Messaging(nextMessagingContext, args.messagingConfig) | ||
this.initFeatureProxy(feature, messaging, origin) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in this POC, I'm delivering hostnames + feature names via UserPreferences - the reason is that during development it would make it significantly easier than having to make changes to remote config. Very much open to suggestions here.
Main Related Task: https://app.asana.com/0/1203581873609357/1205887441046040/f
Tech Design: https://app.asana.com/0/0/1206158388554363/f
Description
Build upon our low-level messaging library by adding a proxy that can live inside isolated contexts and be used to marshal messages from page scripts to native platforms.
NOTE: This is just a POC to aid the conversation in the Tech Design - I used it to successfully implement Duck Player with the macOS handlers removed from the page world.
New Things
ProxyMessagingConfig
Examples
Duck Player, before + after
After: