EXPEDIA GROUP TECHNOLOGY — SOFTWARE
Sizing Android WebView iframes with JavaScript
A debugging war story
Filling the screen of an Android device with a web view is surprisingly difficult. I’d like to share my debugging war story in case it helps you out.
It started with a simple request to display the same iframe our web checkout team uses in the Android traveler app in order to show users 3D Secure (3DS) challenges, part of a two factor authentication protocol for securing online credit and debit card transactions.
Here is the 3DS challenge shown in our existing web checkout flow for reference, along with the mockup from our design team for Android.
I thought, “Oh, pretty simple, just show a web view that fills that screen, and load the URL for the iframe.”
In reality, there were some JavaScript calls mixed in there, but that’s not really relevant to this specific issue. After the JavaScript calls, I’d still expect the iframe to display as above.
The style=”?android:attr/webViewStyle”
and android:focusable=”true”
attributes are needed to allow the user to interact with the displayed web view, tapping and typing and such.
As you can see the WebView
is using match_parent
for both the layout_width
and layout_height
attributes, so we should be good. The ThreeDSWebView
class is simply an extension of the Android WebView
class with some logic for making the related JavaScript calls.
Well, I go through the checkout flow with a property that is supposed to show the 3DS challenge in the web view.
Well then…
As you can see, the iframe shows up as some kind of popup model thing that only covers the top half of the screen.
At first I thought, “No problem, its just a layout issue.” I spun my wheels messing with the layout XML, setting every WebView
value I could think of, and even tried adding viewport meta tags defining the devices size and scaling. Then I did what we all do and Googled the problem. I came across the idea of inspecting the WebView
in Chrome in some Stack Overflow post, so I gave that a shot.
It looked useful, and after poking at it for a bit, I made some adjustments to the elements being shown. First I adjusted the style values in the side bar and then, as I found some that started to make a difference, I turned them into JS commands in the Console.
Look! It actually looks like the intended design there at the end. Now how in the world do I run those JavaScript commands in the app?
It was a little complicated because of how the 3DS challenge is shown. Since it’s the result of a series of JavaScript calls, the styling JavaScript calls needed to be run in a Runnable
that is posted to the UI thread after the JavaScript call that triggers the challenge.
In a less dynamic WebView
situation, that Runnable
with the styling JavaScript calls would probably go in the WebViewClient.onPageFinished()
method set on the WebView
.
Now after running through the checkout flow again things are looking pretty good.
Maybe it’s not an ironclad solution, but it helped us support releasing 3DS challenges quickly by reusing work other teams had already done.