Running a headless WKWebView in Swift - ios

Apple is requiring all Safari extensions to switch over to "Safari App Extensions" which specifies the backend be written in Swift instead of JavaScript.
To reduce rewriting and duplicating code as much as possible I'd like to run a headless WKWebView that runs my current JavaScript code and have Swift act as a bridge to/from the WKWebView JavaScript. (We can't use the JavaScriptCore module because we require WebKit apis like Window, XMLHttpRequest, localstorage, etc)
Currently I'm getting the following errors when trying to load the WKWebView as headless and I think they have to do with the fact that I'm not adding the view as a subview to anything. see com.apple.WebKit.WebContent drops 113 error: Could not find specified service
2018-12-06 17:36:28.464054-0800 Extension[12768:12452197] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
2018-12-06 17:36:28.490149-0800 Extension[12768:12452197] Could not signal service com.apple.WebKit.Networking: 113: Could not find specified service
If anyone has any experience with Swift, WKWebView, Safari App Extensions, etc. your advice would be greatly appreciated. Thanks for reading!

Related

Cross site issue with Microsoft Graph Toolkit

I'm following this tutorial to create a simple web app with a Microsoft 365 login. I'm currently getting this error when debugging locally (http://localhost:8080):
Warning:
mgt-loader.js:61 A parser-blocking, cross site (i.e. different eTLD+1) script, https://unpkg.com/#microsoft/mgt/dist/bundle/wc/webcomponents-loader.js, is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message. See https://www.chromestatus.com/feature/5718547946799104 for more details.
In Azure, I have the Redirect URIs set up to match (http://localhost:8080).
After some googling, I tried adding async, but then I get this warning and the login button doesn't appear:
mgt-loader.js:61 Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.
What would be causing this warning and how can I fix it?
First, check out how document.write works: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
You will understand why you cannot run document.write in asynchronous context (try running document.write('Hello world!'); in console on any page).
Warning tells you that a parser blocking (synchronous), cross site (not coming from the same domain as website) scripts can be blocked by Chrome in the future if someone has unstable or bad internet connection.
If you want it to run synchronously without that warning, you have to bundle that JS code with your own, or just serve it from your own origin, same as your website (e.g. localhost:8080). You can download #microsoft/mgt npm package and for bundling - use gulp, webpack or other tool of your choice.
https://unpkg.com/#microsoft/mgt#2.4.0/dist/bundle/wc/webcomponents-loader.js
This script tries to differentiate between async and sync contexts (line 175) and run document.appendChild (instead of write) for async context - but for some reason the check fails (readyState === loading).
https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
How to check if an Javascript script has been loaded Asynchronously (Async) or async attribute is present?
If you want to run this in non-blocking manner, you could try to fix the script by yourself.
There is a Github repo for that toolkit (https://www.npmjs.com/package/#microsoft/mgt), but there is no issue regarding async loading, nor regarding the warning that you have noticed - so maybe nobody else has noticed or thought about it yet.

importScripts in service worker

I am trying to use IndexedDB through Jakes Archibald's promise-based IDB lib by importScripts but as soon as I select "offline" through Chrome Dev Tools I am getting An unknown error occurred when fetching the script. A funny thing that's happening is that even if shut down my localhost server my app works fine (I have the browser cache disabled through Chrome Dev Tools) on my service worker installed browser but on another, of course, it doesn't.
I've looked into these https://www.w3.org/TR/service-workers/#importscripts, https://github.com/w3c/ServiceWorker/issues/106 resources but I didn't find an fix to my problem.
Any help/explanation would be greatly appreciated.
The problem is likely to be that you've not cached the idb.js file so that the service worker can access it when your app is offline.
Try adding it using cache.add (or cache.addAll if you are caching multiple files) inside your install callback.
Here is a library that i created. It makes using IndexedDB a whole lot easier! completely client-side, no dependencies!
https://github.com/ryanwaite28/promise-db

Google Colaboratory ServiceWorker Error On Chrome

Whenever I open a Colaboratory Document I always get the same error message:
NotSupportedError: Failed to register a ServiceWorker: The user denied permission to use Service Worker.
This is happening on chrome and my browser allows for ServiceWorkers (chrome://serviceworker-internals/), what's going on? Because the thing is all the code still runs.
Colab's output frames use service workers to support some functionality such as displaying richer graphs (Altair and Plot.ly).
The error message indicates that third-party cookies are disabled in your browser, this will prevent the browser service workers from working. The option should be configured under chrome://settings/content/cookies.
I tried white-listing in chrome link (chrome://settings/content/cookies) the following:
https://[*.]googleusercontent.com:443
[*.]colab.research.google.com
Here it was the best approach, better than simply liberatin the 3rd part cookies
Seems to work so on.
Usually there are two causes for this error:
1- you didn't allow cookies on colab domain, so you need to change you browser settings
2- you are using an adblocker

Intern test framework hangs/does nothing when used with Appium 1.4.13 on an iOS device for mobile web

I just started looking into using the intern test framework to write functional tests for our mobile web apps. I'm looking to run these tests on actual iOS devices.
I setup Appium as the selenium server talking to the intern client. It works as expected on the simulator (although I get 'method not implemented' for many of the touch related methods).
I then decided to configure everything to work on my iPhone 6 plus, running iOS 9.0.2
After much wrangling with instructions from here, I got all the various pieces working in tandem (ios-webkit-debug-proxy, appium-server from the repo, etc.)
Finally, I decided to run my tests. When I run the test runner, Safari on my device starts up (via SafariLauncher App), and ios-webkit-debug-proxy and appium-server seem to be talking to each other. However, intern simply posts a 'created session on...' message, and then does nothing.
To ensure that the server was running properly, I decided to use a rest client to send it POST and GET requests using the JSONWire Protocol methods, and it seems to be loading the web-page url and responding to JSONWire requests. So clearly, something is going wrong with Appium talking to intern, or vice-versa.
Any help/insight on this would be greatly appreciated. Thanks!
I'm also in the unique position of having to run these locally, so using SauceLabs, BrowserStack, etc. is out of the question.
Got it working!!!
So the trick was to specify the proxyUrl config option.
My original conjecture was that there might have been some issues with basePath, etc., but I noticed my console.log statements that were outside of test cases were running properly.
That's when I noticed that the Safari page tried to navigate to localhost right after the test had started. This is my first time ever working with Intern or Appium or any Selenium stuff for that matter. Because you cannot access localhost (which in this case was meant for accessing the Intern server on my computer, since you're running the tests on your computer, and not on an external device), from the iPhone, I specified proxyUrl and proxyPort in the config, and specified my computer's local IP (192.168.x.x) and the Intern server port (9000). It still didn't work. I looked at the URL in Safari and noticed that it wasn't using the proxyPort field - so that the URL looked like: 192.168.x.x/__intern/clie... So I just tried to enter the port in the proxyUrl option - as that option's a string - 192.168.x.x:9000. And voila - it worked!!!
So hopefully this helps some other soul looking to have a native mobile test working with this setup!

Dartium and it's use of dart:io

I am building a feature-rich standalone application using dart. I picked dart since it seemed to allow not only the standard development approach for webapps but also to access system resources (such as nodejs does). One of my requirements is file io or database access (which again requires file io). Dartium however does not allow the use of the dart:io package (only in servermode is this library accessible). Can anybody think of a workaround, a change to the dart environment or the chromium environment to allow this ? Maybe a custom compiled dartVM in the browser environemnt.
Basically a way to use database connections in a dart standalone app. A REST wrapper is only an option if this code could get generated automatically.
I am not clear if such a thing is possible or if chromium will prevent any approach to access system resources.
Yes in standalone mode dart you can use files, and also TCP socket, and web socket.
So you can connect to databases. (for example to MySQL: https://github.com/jamesots/sqljocky)
In browser mode you can use built-in databases dart:indexed_db or dart:web_sql.
You can also use web-socket protocol
Maybe you can use websocket to connect with local or remote database.

Resources