The GoBack and GoForward methods on the UWP WebView (x-ms-webview in HTML, Windows.UI.Xaml.Controls.WebView in XAML, and Windows.Web.UI.Interop.WebViewControl in Win32) act the same as the Back
and Forward buttons in the Edge browser. They don't necessarily change the top level document of the WebView. If inside the webview an iframe navigates then that navigation will be recorded in
the forward/back history and the GoBack / GoForward call may result in navigating that iframe. This makes sense as an end user using the Edge browser since if I click a link to navigate one place
and then hit Back I expect to sort of undo that most recent navigation regardless of if that navigation happened in an iframe or the top level document.
If that doesn't make sense for your application and you want to navigate forward or back ignoring iframe navigates, unfortunately there's no perfect workaround.
One workaround could be to try calling GoBack and then checking if a FrameNavigationStarting event fires or a NavigationStarting event fires. If a frame navigates then try calling GoBack again.
There could be async races in this case since other navigates could come in and send you the wrong signal and interrupt your multi step GoBack operation.
You could also try keeping track of all top level document navigations and manually navigate back to the URIs you care about. However, GoBack and GoForward also restore some amount of user state
(form fills etc) in addition to navigating. Manually calling navigate will not give this same behavior.
JSBrowser is a basic browser built as a Win10 JavaScript UWP app around the WebView HTML element. Its fun and relatively simple to
implement tiny browser features in JavaScript and in this post I'm implementing crash resistance.
The normal DOM mechanisms for creating an HTML WebView create an in-process WebView, in which the WebView runs on a
unique UI thread. But we can use the MSWebView constructor instead to create an out-of-process WebView in which the WebView runs in its own distinct WebView process. Unlike an in-process WebView,
Web content running in an out-of-process WebView can only crash the WebView process and not the app process.
this.replaceWebView = () => { let webview = document.querySelector("#WebView"); // Cannot access webview.src - anything that would need to communicate with the webview process may fail let oldSrc = browser.currentUrl; const webviewParent = webview.parentElement; webviewParent.removeChild(webview); webview = new MSWebView(); Object.assign(this, { "webview": webview }); webview.setAttribute("id", "WebView");
// During startup our currentUrl field is blank. If the WebView has crashed // and we were on a URI then we may obtain it from this property. if (browser.currentUrl && browser.currentUrl != "") { this.trigger("newWebview"); this.navigateTo(browser.currentUrl); } webviewParent.appendChild(webview);
I run replaceWebView during startup to replace the in-process WebView created via HTML markup with an out-of-process WebView. I could be doing more to dynamically copy styles, attributes, etc but
I know what I need to set on the WebView and just do that.
When a WebView process crashes the corresponding WebView object is no longer useful and a new WebView element must be created. In fact if the old WebView object is used it may throw and will no
longer have valid state. Accordingly when the WebView crashes I run replaceWebView again. Additionally, I need to store the last URI we've navigated to (browser.currentUrl in the above) since the
crashed WebView object won't know what URI it is on after it crashes.
webview.addEventListener("MSWebViewProcessExited", () => { if (browser.currentUrl === browser.lastCrashUrl) { ++browser.lastCrashUrlCrashCount; } else { browser.lastCrashUrl = browser.currentUrl; browser.lastCrashUrlCrashCount = 1; } // If we crash again and again on the same URI, maybe stop trying to load that URI. if (browser.lastCrashUrlCrashCount >= 3) { browser.lastCrashUrl = ""; browser.lastCrashUrlCrashCount = 0; browser.currentUrl = browser.startPage; } this.replaceWebView(); });
I also keep track of the last URI that we recovered and how many times we've recovered that same URI. If the same URI crashes more than 3 times in a row then I assume that it will keep happening
and I navigate to the start URI instead.
The documentation for printing in JavaScript UWP apps is out of date as it all references MSApp.getHtmlPrintDocumentSource but that method has been replaced by MSApp.getHtmlPrintDocumentSourceAsync since WinPhone
8.1.
Background
Previous to WinPhone 8.1 the WebView's HTML content ran on the UI thread of the app. This is troublesome for rendering arbitrary web content since in the extreme case the JavaScript of some
arbitrary web page might just sit in a loop and never return control to your app's UI. With WinPhone 8.1 we added off thread WebView in which the WebView runs HTML content on a separate UI
thread.
Off thread WebView required changing our MSApp.getHtmlPrintDocumentSource API which could no longer synchronously produce an HtmlPrintDocumentSource. With WebViews running on their own threads it
may take some time for them to generate their print content for the HtmlPrintDocumentSource and we don't want to hang the app's UI thread in the interim. So the MSApp.getHtmlPrintDocumentSource
API was replaced with MSApp.getHtmlPrintDocumentSourceAsync which returns a promise the resolved value of which is the eventual HtmlPrintDocumentSource.
Sample
However, the usage of the API is otherwise unchanged. So in sample code you see referencing MSApp.getHtmlPrintDocumentSource the sample code is still reasonable but you need to call
MSApp.getHtmlPrintDocumentSourceAsync instead and wait for the promise to complete. For example the PrintManager docs has an example implementing a PrintTaskRequested event handler in a JavaScript UWP app.
function onPrintTaskRequested(printEvent) { var printTask = printEvent.request.createPrintTask("Print Sample", function (args) { args.setSource(MSApp.getHtmlPrintDocumentSource(document)); });
Instead we need to obtain a deferral in the event handler so we can asynchronously wait for getHtmlPrintDocumentSourceAsync to complete:
The x-ms-webview HTML element has the void addWebAllowedObject(string name, any value) method and the webview
XAML element has the void AddWebAllowedObject(String name,
Object value) method. The object parameter is projected into the webview’s top-level HTML document’s script engine as a new property on the global object with property name set to the name
parameter. It is not injected into the current document but rather it is projected during initialization of the next top-level HTML document to which the webview navigates.
Lifetime
If AddWebAllowedObject is called during a NavigationStarting event handler the object will be injected into the document resulting from the navigation corresponding to that event.
If AddWebAllowedObject is called outside of the NavigationStarting event handler it will apply to the navigation corresponding to the next explicit navigate method called on the webview or the
navigation corresponding to the next NavigationStarting event handler that fires, whichever comes first.
To avoid this potential race, you should use AddWebAllowedObject in one of two ways: 1. During a NavigationStarting event handler, 2. Before calling a Navigate method and without returning to the
main loop.
If called both before calling a navigate method and in the NavigationStarting event handler then the result is the aggregate of all those calls.
If called multiple times for the same document with the same name the last call wins and the previous are silently ignored.
If AddWebAllowedObject is called for a navigation and that navigation fails or redirects to a different URI, the AddWebAllowedObject call is silently ignored.
After successfully adding an object to a document, the object will no longer be projected once a navigation to a new document occurs.
WinRT access
If AddWebAllowedObject is called for a document with All WinRT access then projection will succeed and the object will be added.
If AddWebAllowedObject is called for a document which has a URI which has no declared WinRT access via ApplicationContentUriRules then Allow for web only WinRT access is given to that document.
If the document has Allow for web only WinRT access then projection will succeed only if the object’s runtimeclass has the Windows.Foundation.Metadata.AllowForWeb metadata attribute.
Object requirements
The object must implement the IAgileObject interface. Because the XAML and HTML webview elements run on ASTA view threads and the webview’s content’s JavaScript thread runs on another ASTA thread
a developer should not create their non-agile runtimeclass on the view thread. To encourage end developers to do this correctly we require the object implements IAgileObject.
Property name
The name parameter must be a valid JavaScript property name, otherwise the call will fail silently. If the name is already a property name on the global object, that property is overwritten if
the property is configurable. Non-configurable properties on the global object are not overwritten and the AddWebAllowedObject call fails silently. On success, the projected property is writable,
configurable, and enumerable.
Errors
Some errors as described above fail silently. Other issues, such as lack of IAgileObject or lack of the AllowForWeb attribute result in an error in the JavaScript developer console.
JavaScript Microsoft Store apps have some details related to activation that are specific to JavaScript Store apps and that are poorly documented which I’ll describe here.
StartPage syntax
The StartPage attributes in the AppxManifest.xml (Package/Applications/Application/@StartPage, Package/Applications/Extensions/Extension/@StartPage) define the HTML page entry point for
that kind of activation. That is, Application/@StartPage defines the entry point for tile activation, Extension[@Category="windows.protocol"]/@StartPage defines the entry point for URI handling
activation, etc. There are two kinds of supported values in StartPage attributes: relative Windows file paths and absolute URIs. If the attribute doesn’t parse as an absolute URI then it is
instead interpreted as relative Windows file path.
This implies a few things that I’ll declare explicitly here. Windows file paths, unlike URIs, don’t have a query or fragment, so if you are using a relative Windows file path for your StartPage
attribute you cannot include anything like ‘?param=value’ at the end. Absolute URIs use percent-encoding for reserved characters like ‘%’ and ‘#’. If you have a ‘#’ in your HTML filename then you
need to percent-encode that ‘#’ for a URI and not for a relative Windows file path.
If you specify a relative Windows file path, it is turned into an ms-appx URI by changing all backslashes to forward slashes, percent-encoding reserved characters, and combining the result with a
base URI of ms-appx:///. Accordingly the relative Windows file paths are relative to the root of your package. If you are using a relative Windows file path as your StartPage and need to switch
to using a URI so you can include a query or fragment, you can follow the same steps above.
StartPage validity
The validity of the StartPage is not determined before activation. If the StartPage is a relative Windows file path for a file that doesn’t exist, or an absolute URI that is not in the
Application Content URI Rules, or something that doesn’t parse as a Windows file path or URI, or otherwise an absolute URI that fails to resolve (404, bad hostname, etc etc) then the JavaScript
app will navigate to the app’s navigation error page (perhaps more on that in a future blog post). Just to call it out explicitly because I have personally accidentally done this: StartPage URIs
are not automatically included in the Application Content URI Rules and if you forget to include your StartPage in your ACUR you will always fail to navigate to that StartPage.
StartPage navigation
When your app is activated for a particular activation kind, the StartPage value from the entry in your app’s manifest that corresponds to that activation kind is used as the navigation target.
If the app is not already running, the app is activated, navigated to that StartPage value and then the Windows.UI.WebUI.WebUIApplication activated event is fired (more details on
the order of various events in a moment). If, however, your app is already running and an activation occurs, we navigate or don’t navigate to the corresponding StartPage depending on the current
page of the app. Take the app’s current top level document’s URI and if after removing the fragment it already matches the StartPage value then we won’t navigate and will jump straight to firing
the WebUIApplication activated event.
Since navigating the top-level document means destroying the current JavaScript engine instance and losing all your state, this behavior might be a problem for you. If so, you can use the
MSApp.pageHandlesAllApplicationActivations(true) API to always skip navigating to the StartPage and instead always jump straight to firing the WebUIApplication activated event. This
does require of course that all of your pages all handle all activation kinds about which any part of your app cares.
Application Content URI Rules (ACUR from now on) defines the bounds of
the web that make up the Microsoft Store application. Package content via the ms-appx URI scheme is automatically considered part of the app. But if you have content on the web via http or https
you can use ACUR to declare to Windows that those URIs are also part of your application. When your app navigates to URIs on the web those URIs will be matched against the ACUR to determine if
they are part of your app or not. The documentation for how matching is done on the wildcard URIs in the ACUR Rule elements is not very helpful on MSDN so here are some notes.
Rules
You can have up to 100 Rule XML elements per ApplicationContentUriRules element. Each has a Match attribute that can be up to 2084 characters long. The content of the Match attribute is parsed
with CreateUri and when matching against URIs on the web additional wildcard processing is performed. I’ll call the
URI from the ACUR Rule the rule URI and the URI we compare it to found during app navigation the navigation URI.
The rule URI is matched to a navigation URI by URI component: scheme, username, password, host, port, path, query, and fragment. If a component does not exist on the rule URI then it matches any
value of that component in the navigation URI. For example, a rule URI with no fragment will match a navigation URI with no fragment, with an empty string fragment, or a fragment with any value
in it.
Asterisk
Each component except the port may have up to 8 asterisks. Two asterisks in a row counts as an escape and will match 1 literal asterisk. For scheme, username, password, query and fragment the
asterisk matches whatever it can within the component.
Host
For the host, if the host consists of exactly one single asterisk then it matches anything. Otherwise an asterisk in a host only matches within its domain name label. For example,
http://*.example.com will match http://a.example.com/ but not http://b.a.example.com/ or http://example.com/. And http://*/ will match http://example.com, http://a.example.com/, and
http://b.a.example.com/. However the Store places restrictions on submitting apps that use the http://* rule or rules with an asterisk in the second effective domain name label. For example,
http://*.com is also restricted for Store submission.
Path
For the path, an asterisk matches within the path segment. For example, http://example.com/a/*/c will match http://example.com/a/b/c and http://example.com/a//c but not http://example.com/a/b/b/c
or http://example.com/a/c
Additionally for the path, if the path ends with a slash then it matches any path that starts with that same path. For example, http://example.com/a/ will match http://example.com/a/b and
http://example.com/a/b/c/d/e/, but not http://example.com/b/.
If the path doesn’t end with a slash then there is no suffix matching performed. For example, http://example.com/a will match only http://example.com/a and no URIs with a different path.
As a part of parsing the rule URI and the navigation URI, CreateUri will perform URI normalization and so the hostname and scheme will be made lower case (casing matters in all other parts of the
URI and case sensitive comparisons will be performed), IDN normalization will be performed, ‘.’ and ‘..’ path segments will be resolved and other normalizations as described in the CreateUri
documentation.
2016-Nov-5: Updated post on using Let's Encrypt with NearlyFreeSpeech.net
I use NearlyFreeSpeech.net for my webhosting for my personal website and I've just finished setting up TLS via Let's Encrypt. The process was slightly more complicated than what you'd like from
Let's Encrypt. So for those interested in doing the same on NearlyFreeSpeech.net, I've taken the following notes.
The standard Let's Encrypt client requires su/sudo access which is not available on NearlyFreeSpeech.net's servers. Additionally NFSN's webserver doesn't have any Let's Encrypt plugins installed.
So I used the Let's Encrypt Without Sudo client. I followed the instructions listed on the tool's page with the addition of providing
the "--file-based" parameter to sign_csr.py.
Now that you have all the required files, on your NFSN server make the directory /home/protected/ssl and copy your files into it. This is described in the NFSN topic provide certificates to NFSN. After copying the files and setting their permissions as described in the previous link you submit
an assistance request. For me it was only 15 minutes later that everything was setup.
After enabling HTTPS I wanted to have all HTTP requests redirect to HTTPS. The normal Apache documentation on how to do this doesn't work on NFSN servers. Instead the NFSN FAQ describes it in
"redirect http to https and HSTS". You use the X-Forwarded-Proto instead of the HTTPS variable because of how NFSN's
virtual hosting is setup.
RewriteEngine on RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]
Turning on HSTS is as simple as adding the HSTS HTTP header. However, the description in the above link didn't work because my site's NFSN realm isn't on the latest Apache yet. Instead I added
the following to my .htaccess. After I'm comfortable with everything working well for a few days I'll start turning up the max-age to the recommended minimum value of 180 days.
Header set Strict-Transport-Security "max-age=3600;"
Finally, to turn on CSP I started up Fiddler with my CSP Fiddler extension. It allows me to determine the most restrictive CSP
rules I could apply and still have all resources on my page load. From there I found and removed inline script and some content loaded via http and otherwise continued tweaking my site and CSP
rules.
After I was done I checked out my site on SSL Lab's SSL Test to see what I might have done wrong or needed improving. The first time I went through
these steps I hadn't included the chain file which the SSL Test told me about. I was able to add that file to the same files I had already previously generated from the Let's Encrypt client and
do another NFSN assistance request and 15 minutes later the SSL Test had upgraded me from 'B' to 'A'.
This 30 day mission will help our researchers learn how isolation and close quarters affect individual and group behavior. This study at our Johnson Space Center prepares us for long duration
space missions, like a trip to an asteroid or even to Mars.
The Human Research Exploration Analog (HERA) that the crew members will be living in is one compact, science-making house. But
unlike in a normal house, these inhabitants won’t go outside for 30 days. Their communication with the rest of planet Earth will also be very limited, and they won’t have any access to
internet. So no checking social media kids!
The only people they will talk with regularly are mission control and each other.
The crew member selection process is based on a number of criteria, including the same criteria for astronaut selection.
What will they be doing?
Because this mission simulates a 715-day journey to a Near-Earth asteroid, the four crew members will complete activities similar to what would happen during an outbound transit, on location at
the asteroid, and the return transit phases of a mission (just in a bit of an accelerated timeframe). This simulation means that even when communicating with mission control, there will be a
delay on all communications ranging from 1 to 10 minutes each way. The crew will also perform virtual spacewalk missions once they reach their destination, where they will inspect the asteroid
and collect samples from it.
A few other details:
The crew follows a timeline that is similar to one used for the ISS crew.
They work 16 hours a day, Monday through Friday. This includes time for daily planning, conferences, meals and exercises.
They will be growing and taking care of plants and brine shrimp, which they will analyze and document.
But beware! While we do all we can to avoid crises during missions, crews need to be able to respond in the event of an emergency. The HERA crew will conduct a couple of emergency scenario
simulations, including one that will require them to maneuver through a debris field during the Earth-bound phase of the mission.
Throughout the mission, researchers will gather information about cohabitation, teamwork, team cohesion, mood, performance and overall well-being. The crew members will be tracked by numerous
devices that each capture different types of data.
Past HERA crew members wore a sensor that recorded heart rate, distance, motion and sound intensity. When crew members were
working together, the sensor would also record their proximity as well, helping investigators learn about team cohesion.
Researchers also learned about how crew members react to stress by recording and analyzing verbal interactions and by analyzing “markers” in blood and saliva samples.
In total, this mission will include 19 individual investigations across key human research elements. From psychological to physiological experiments, the crew members will help prepare us for
future missions.
This 30 day mission will help our researchers learn how isolation and close quarters affect individual and group behavior. This study at our Johnson Space Center prepares us for long duration
space missions, like a trip to an asteroid or even to Mars.
The Human Research Exploration Analog (HERA) that the crew members will be living in is one compact, science-making house. But
unlike in a normal house, these inhabitants won’t go outside for 30 days. Their communication with the rest of planet Earth will also be very limited, and they won’t have any access to
internet. So no checking social media kids!
The only people they will talk with regularly are mission control and each other.
The crew member selection process is based on a number of criteria, including the same criteria for astronaut selection.
What will they be doing?
Because this mission simulates a 715-day journey to a Near-Earth asteroid, the four crew members will complete activities similar to what would happen during an outbound transit, on location at
the asteroid, and the return transit phases of a mission (just in a bit of an accelerated timeframe). This simulation means that even when communicating with mission control, there will be a
delay on all communications ranging from 1 to 10 minutes each way. The crew will also perform virtual spacewalk missions once they reach their destination, where they will inspect the asteroid
and collect samples from it.
A few other details:
The crew follows a timeline that is similar to one used for the ISS crew.
They work 16 hours a day, Monday through Friday. This includes time for daily planning, conferences, meals and exercises.
They will be growing and taking care of plants and brine shrimp, which they will analyze and document.
But beware! While we do all we can to avoid crises during missions, crews need to be able to respond in the event of an emergency. The HERA crew will conduct a couple of emergency scenario
simulations, including one that will require them to maneuver through a debris field during the Earth-bound phase of the mission.
Throughout the mission, researchers will gather information about cohabitation, teamwork, team cohesion, mood, performance and overall well-being. The crew members will be tracked by numerous
devices that each capture different types of data.
Past HERA crew members wore a sensor that recorded heart rate, distance, motion and sound intensity. When crew members were
working together, the sensor would also record their proximity as well, helping investigators learn about team cohesion.
Researchers also learned about how crew members react to stress by recording and analyzing verbal interactions and by analyzing “markers” in blood and saliva samples.
In total, this mission will include 19 individual investigations across key human research elements. From psychological to physiological experiments, the crew members will help prepare us for
future missions.
"A routine request in Florida for records detailing the use of a surveillance tool known as stingray turned extraordinary Tuesday when the U.S. Marshals Service seized the documents before local
police could release them."
Also what about the part where the PD reveals that its been using the stingray a bunch without telling any court and blames that on the manufacturer’s NDA.
The DOM location interface exposes the HTML document's URI parsed into its properties. However, it is
ancient and has problems that bug me but otherwise rarely show up in the real world. Complaining about mostly theoretical issues is why blogging exists, so here goes:
The location object's search, hash, and protocol properties are all misnomers that lead to confusion about the correct terms:
The 'search' property returns the URI's query property. The query property isn't limited to containing search terms.
The 'hash' property returns the URI's fragment property. This one is just named after its delimiter. It should be called the fragment.
The 'protocol' property returns the URI's scheme property. A URI's scheme isn't necessarily a protocol. The http URI scheme of course uses the HTTP protocol, but the https URI scheme is
the HTTP protocol over SSL/TLS - there is no HTTPS protocol. Similarly for something like mailto - there is no mailto wire protocol.
The 'hash' and 'search' location properties both return null in the case that their corresponding URI property doesn't exist or if its the
empty string. A URI with no query property and a URI with an empty string query property that are otherwise the same, are not equal URIs and are allowed by HTTP to return different content.
Similarly for the fragment. Unless the specific URI scheme defines otherwise, an empty query or hash isn't the same as no query or
hash.
But like complaining about the number of minutes in an hour none of this can ever change without huge compat issues on the web.
Accordingly I can only give my thanks to Anne van Kesteren and the awesome work on the URL standard moving towards a more sane (but still working
practically within the constraints of compat) location object and URI parsing in the browser.
This entry covers the historical context of Space War!, and instructions for working with our in-browser emulator. The system doesn’t require installed plugins (although a more powerful machine
and recent browser version is suggested).
The JSMESS emulator (a conversion of the larger MESS project) also contains a real-time portrayal of the lights and switches of a Digital PDP-1, as well as
links to documentation and manuals for this $800,000 (2014 dollars) minicomputer.
You’ve gotta watch this Super Smash Bros. Melee documentary that follows some of the top players in the scene—it’s quite good. Accessible, too: you don’t need to be a fox-only no-items final
destination type player to enjoy it; they break the game down wonderfully.
I just got a FitBit One from my wife. Unfortunately I had issues running their app on my Windows 8.1 Preview machine. But I recognized the errors as IE compatibility issues, for instance an IE
dialog popup from the FitBit app telling me about an error in the app's JavaScript. Given my previous post on WebOC versioning you may guess what I tried next. I
went into the registry and tried out different browser mode and document mode versions until I got the FitBit software running without error. Ultimately I found the following registry value to work
well ('FitBit connect.exe' set to DWORD decimal 8888).
For
those familiar with the Windows registry the above should be enough. For those not familiar, copy and paste the above into notepad, save as a file named "fitbit.reg", and then double click the reg
file and say 'Yes' to the prompt. Hopefully in the final release of Windows 8.1 this won't be an issue.