FYI the version with automatic secret per each JSONChannel instance is there. You can provide a secret from GJS for a global channel or accept any channel ... it's your call on security side, really.
Regards On Wed, Nov 1, 2017 at 2:44 PM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > OK, I've done some test and apparently `notify::title` is queue so even if > you change title twice in a row in WebKit/JS land, GJS will receive all > changes. > > This made me able to create a simple JSONChannel class: > https://gist.github.com/WebReflection/7ab0addec037508cc8380a9c37d285f2 > > I have that class and the following code in a browser.js file > > ```js > > const PageChannel = new JSONChannel('super-secret'); > PageChannel > .on('message', (err, data) => { > if (err) console.error(err); > else console.log(data); > }) > .send('ping'); > > ``` > > The index page is nothing more than just this: > ```html > > <!doctype html> > <script src="browser.js"></script> > > ``` > > The GJS part, simplified for demo purpose, is basically just this > ```js > > const secret = 'super-secret';const re = new > RegExp(`^${secret}:js=`);webView.connect('notify::title', (self, params) => { > if (re.test(self.title)) { > const data = JSON.parse(self.title.slice(RegExp['$&'].length)); > print(data); > self.run_javascript( > `document.dispatchEvent( new CustomEvent( > '${secret}:gjs', {detail: ${JSON.stringify('pong')}} ) > );`, > null, > (self, result, error) => { > self.run_javascript_finish(result); > } > ); > } > }); > > ``` > > > You will see ping followed by pong in the console once you load that > index.html > > Please note that document.title changes could be intercepted via > MutationObserver or DOMSubtreeModified on a document with a title element > and/or hacking the title accessor itself or the document, meaning the > "secret" is not really secret but it's a way to setup a unique channel. > > There could be a convention to setup a channel automatically adding some > extra logic on both sides (and I'll giv it a try in few minutes) but I hope > you got the proof of concept and it works for your needs. > > It's simpler to implement than my hack on location and it works > better/faster. > > Regards > > > > > > > On Wed, Nov 1, 2017 at 1:17 PM, Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> I'd be OK if WebKitGTK could at least accept strings and pass them along >> ... wkjscore-result should be part of the core, IMO. >> >> >> >> On Wed, Nov 1, 2017 at 12:28 PM, Sam Jansen <sam.jan...@starleaf.com> >> wrote: >> >>> >>> >>> On 1 November 2017 at 15:23, Andrea Giammarchi < >>> andrea.giammar...@gmail.com> wrote: >>> >>>> so ... it looks really like the exposed API is completely useless as it >>>> is >>>> >>>> ```js >>>> webkit.messageHandlers.gjs.postMessage('hello'); >>>> ``` >>>> >>>> Returns a >>>> >>>> [boxed instance proxy GIName:WebKit2.JavascriptResult >>>> jsobj@0x7fa08c2e4160 native@0x7fa052081d80] >>>> >>>> >>>> and if you try to get its value it goes bananas with a message like: >>>> >>>> Gjs-WARNING **: JS ERROR: Error: Unable to find module implementing >>>> foreign type JavaScriptCore.Value >>>> >>>> >>>> What's the purpose of register_script_message_handler at all? What am >>>> I missing? >>>> >>>> >>> Andrea, this is the problem Philip raised earlier and I replied to. I >>> use this library to solve the problem: https://github.com/sa >>> ifulbkhan/wkjscore-result >>> >>> 7 import * as WkJsCore from '../../gjs/WkJsCore' >>> ... >>> 85 let contentManager = this.webkit.get_user_content_manager(); >>> 86 if (!contentManager.register_scri >>> pt_message_handler('slinternal')) { >>> 87 throw "register_script_message_handler() failed"; >>> 88 } >>> 89 contentManager.connect("script-message-received::foobar", >>> (obj, jsResult) => { >>> 90 let wkResult = WkJsCore.Result.new(jsResult); >>> 91 let str = wkResult.process_result_as_string(); >>> >>> >>> Unfortunately JavaScriptCore doesn't provide it's own GIR API to access >>> the JS data :( >>> >>> >>>> >>>> >>>> On Wed, Nov 1, 2017 at 11:02 AM, Andrea Giammarchi < >>>> andrea.giammar...@gmail.com> wrote: >>>> >>>>> I've quickly provided a proof of concept but you could have a >>>>> JSONChannel class singleton on the client side that queue each info and >>>>> wait for the GJS side to receive one before sending another. >>>>> >>>>> I might try a real implementation though and see how it works. >>>>> >>>>> however, this is just a work around for the fact you can send messages >>>>> without any content (... and I wonder how that can be useful in any way >>>>> ...) >>>>> >>>>> Regards >>>>> >>>>> On Wed, Nov 1, 2017 at 10:50 AM, Sam Jansen <sam.jan...@starleaf.com> >>>>> wrote: >>>>> >>>>>> >>>>>> >>>>>> On 1 November 2017 at 11:55, Andrea Giammarchi < >>>>>> andrea.giammar...@gmail.com> wrote: >>>>>> >>>>>>> Actually the `notify::title` with a prefixed "secret-channel" and >>>>>>> serialized JSON looks like the best of them all, for the time being, as >>>>>>> it >>>>>>> makes it straight forward for both client and server to communicate. >>>>>>> >>>>>>> ```js >>>>>>> // listen to each response >>>>>>> new MutationObserver(m => { >>>>>>> if (/^secret:response=/.test(document.title)) { >>>>>>> const data = JSON.parse(document.title.slic >>>>>>> e(RegExp['$&'].length)); >>>>>>> document.title = ''; >>>>>>> console.log(data); >>>>>>> } >>>>>>> }).observe( >>>>>>> document.querySelector('title'), >>>>>>> {childList: true} >>>>>>> ); >>>>>>> >>>>>>> // send info using client or simulate server sending in responses >>>>>>> document.title = 'secret:response=' + JSON.stringify({some: >>>>>>> 'value'}); >>>>>>> ``` >>>>>>> >>>>>>> with a proper class/wrap to handle events and send data >>>>>>> transparently it might be a great way to exchange info >>>>>>> >>>>>>> >>>>>> I've just come to the opposite conclusion, though I don't disagree as >>>>>> such... >>>>>> >>>>>> My concern is that setting document.title, and having notify::title >>>>>> called is asynchronous (I believe). So in your JS, if one had: >>>>>> >>>>>> ``` >>>>>> document.title = '1' >>>>>> document.title = '2' >>>>>> ``` >>>>>> >>>>>> Then by the time notify::title is called, and you inspect your >>>>>> "webkit.title" property, I'd expect you'd only see the '2' value, and >>>>>> (likely) not the '1'. >>>>>> >>>>>> It's possible to solve this by ensuring the GJS side has picked up a >>>>>> message, and e.g. reset the title, I suppose. This feels like an awkward >>>>>> solution to me though. >>>>>> >>>>>> >>>>>>> >>>>>>> >>>>>>> On Wed, Nov 1, 2017 at 5:53 AM, Sam Jansen <sam.jan...@starleaf.com> >>>>>>> wrote: >>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On 1 November 2017 at 05:43, <philip.chime...@gmail.com> wrote: >>>>>>>> >>>>>>>>> On Thu, Oct 12, 2017 at 5:23 AM Andrea Giammarchi < >>>>>>>>> andrea.giammar...@gmail.com> wrote: >>>>>>>>> >>>>>>>>>> FWIW I've used the location with a private channel as protocol to >>>>>>>>>> intercept calls to/from the page and GJS. >>>>>>>>>> >>>>>>>>>> https://github.com/WebReflection/jsgtk-twitter/blob/master/a >>>>>>>>>> pp#L162-L175 >>>>>>>>>> >>>>>>>>>> The channel is a random string: https://github.com/Web >>>>>>>>>> Reflection/jsgtk-twitter/blob/master/app#L59 >>>>>>>>>> >>>>>>>>>> From the page, which is aware of the "secret" channel, I call GJS >>>>>>>>>> actions via location.href = `secret1234:method(${encodeURI >>>>>>>>>> Component(JSON.stringify(value))})`; >>>>>>>>>> >>>>>>>>>> The protocol secret1234 is intercepted and the >>>>>>>>>> `controller.method(JSON.parse(decodeURIComponent(restOfURI)))` >>>>>>>>>> invoked. >>>>>>>>>> >>>>>>>>>> To signal the page everything is fine I use >>>>>>>>>> this.webView.runJavaScript https://github.com/WebReflect >>>>>>>>>> ion/jsgtk-twitter/blob/master/app#L377 >>>>>>>>>> >>>>>>>>>> The page has a listener for the `secret1234` event on the main >>>>>>>>>> window, and such listener is instrumented to react accordingly with >>>>>>>>>> the >>>>>>>>>> CustomEvent .detail payload/info. >>>>>>>>>> >>>>>>>>>> This might look a bit convoluted, and it has JSON serialization >>>>>>>>>> as limitation for the kind of data you want to pass (i.e. I use >>>>>>>>>> base64 >>>>>>>>>> encoded images as source from remotely fetched files enabling >>>>>>>>>> somehow CORS >>>>>>>>>> for whatever I want) but it worked well, circumventing the missing >>>>>>>>>> communication channel available in Qt. >>>>>>>>>> >>>>>>>>>> Maybe today there are better ways for doing a similar thing and >>>>>>>>>> if that's the case, please share. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Here is another, fairly new, way to do it. Start out by >>>>>>>>> registering a "script message handler": >>>>>>>>> http://devdocs.baznga.org/webkit240~4.0_api/webkit2.usercont >>>>>>>>> entmanager#method-register_script_message_handler >>>>>>>>> >>>>>>>>> To send a message to the page, use the same thing that Andrea uses: >>>>>>>>> http://devdocs.baznga.org/webkit240~4.0_api/webkit2.webview# >>>>>>>>> method-run_javascript >>>>>>>>> >>>>>>>>> To send a message from the page to the GJS program, use the >>>>>>>>> postMessage() method mentioned in the documentation, and connect to >>>>>>>>> this >>>>>>>>> signal in your GJS program to receive the message: >>>>>>>>> http://devdocs.baznga.org/webkit240~4.0_api/webkit2.usercont >>>>>>>>> entmanager#signal-script-message-received >>>>>>>>> >>>>>>>>> >>>>>>>> Excellent - I had not noticed this. My first attempt at >>>>>>>> communicating between WebKit2 and GJS was via setting "document.title" >>>>>>>> and >>>>>>>> having GJS connect to the "notify::title" signal! Not a great approach, >>>>>>>> this looks much better. >>>>>>>> >>>>>>>> >>>>>>>>> Although I just realized that unfortunately the values won't be >>>>>>>>> able to be marshalled into GJS since you need to use the >>>>>>>>> JavaScriptCore API >>>>>>>>> to get at them. This is a really nice method in C, but in JS you can >>>>>>>>> only >>>>>>>>> use it to send a message without any content. That is annoying. I >>>>>>>>> should >>>>>>>>> probably open up an issue about this. >>>>>>>>> >>>>>>>>> >>>>>>>> I just hit upon this problem myself. In researching it, I found it >>>>>>>> is solved (at least well enough for my use-case) with this open source >>>>>>>> library: >>>>>>>> >>>>>>>> https://github.com/saifulbkhan/wkjscore-result >>>>>>>> >>>>>>>> It's awkward having another dependency for me, especially one that >>>>>>>> isn't in a normal Ubuntu/Fedora/etc. package, but otherwise this >>>>>>>> approach >>>>>>>> worked fine for me. >>>>>>>> >>>>>>>> >>>>>>>>> On Wed, Oct 11, 2017 at 12:57 PM, Adriano Patrizio < >>>>>>>>>> adriano.patri...@hotmail.com> wrote: >>>>>>>>>> >>>>>>>>>>> Thank you for response, this is my problem: have necessity to >>>>>>>>>>> implement methods into my web application webkit2 based and >>>>>>>>>>> comunicate with >>>>>>>>>>> GJS script (example: filesystem functions to read and write files >>>>>>>>>>> or window >>>>>>>>>>> managment). >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> Regards, >>>>>>>>> Philip C >>>>>>>>> >>>>>>>>> _______________________________________________ >>>>>>>>> javascript-list mailing list >>>>>>>>> javascript-list@gnome.org >>>>>>>>> https://mail.gnome.org/mailman/listinfo/javascript-list >>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> >
_______________________________________________ javascript-list mailing list javascript-list@gnome.org https://mail.gnome.org/mailman/listinfo/javascript-list