blob: 82cd118251a5678e01517a5dd8b5e59c3ccceb6d [file] [log] [blame] [view]
Richard Colesf369ba92020-12-16 21:27:061# Web platform compatibility in Android WebView
2
3The Android WebView sometimes needs special consideration and care when making
4changes to web platform APIs and behaviours. Chromium developers who make these
5changes (especially deliberate interventions) may want to consult this
6documentation and/or reach out to the WebView team if they're unsure how a
7change might affect WebView.
8
9[TOC]
10
11## Why is WebView special when it comes to compatibility?
12
13### Android has a different approach to compatibility than the web: targetSdkVersion
14
15WebView is part of the Android platform and very widely used in the Android app
16ecosystem. Android tries hard to avoid making backward-incompatible changes to
17the platform; existing apps (including those the user may have paid for) are
18expected to continue to work after an OS update.
19
20One key way this is achieved is that Android apps declare a
21[target SDK version](https://developer.android.com/guide/topics/manifest/uses-sdk-element)
22in their manifest; this specifies the latest version of the Android SDK that the
23developer considered and tested against. Behaviour changes and new restrictions
24in the platform are often only applied to apps which target at least the version
25in which those changes were introduced; this allows already-published apps to
26remain unaffected by the changes. Android's
27[release notes](https://developer.android.com/about/versions/10/behavior-changes-10)
28for developers call out which changes developers can expect to see when they
29update their app's target SDK to the latest version, to make it easier to test
30and update apps.
31
32To avoid apps continuing to target old SDK versions forever (e.g. to permanently
33avoid newly introduced restrictions), the Play Store
34[enforces a minimum](https://developer.android.com/distribute/best-practices/develop/target-sdk)
35when developers upload app binaries to the store: new and updated apps must
36target a sufficiently recent version. However, there is no enforcement applied
37to existing app binaries: apps that are updated very infrequently or which are
38no longer being actively developed at all remain on the store, and may still
39target much older SDK versions. This means that the number of apps requiring any
40particular piece of backward-compatibility code drops over time, but never to
41zero, and in most cases Android retains the backward-compatible code path
42indefinitely.
43
44This means that even though WebView has been receiving frequent updates since
45Android 5.0, app developers often still expect that incompatible changes to its
46behaviour only happen in new Android releases.
47
48### Android's Compatibility Test Suite tests some WebView behaviours
49
50Android relies on the
51[**Compatibility Test Suite** (**CTS**)](https://source.android.com/compatibility/cts)
52to ensure that different devices' implementations of Android are compatible with
53each other. CTS is versioned alongside the Android OS; any Android 10 device is
54expected to pass CTS version 10, and so on. CTS does have minor version updates
55to address bugs in the tests themselves, such as flakiness or assumptions that
56are discovered not to be valid on all devices; see
57[WebView's CTS docs](./tools/cts_config/README.md#changing-cts-tests-retroactively)
58for more information on when this may be appropriate.
59
60CTS contains a number of tests which test the WebView's APIs and behaviours, and
61it's expected that these tests will pass even if the device has been updated to
62the latest version of WebView. This presents a significant problem for web
63platform changes if they cause an existing CTS test to fail; this means WebView
64is no longer compatible with that Android version's expectations, and the entire
65point of those expectations is that apps may also rely on them. CTS test
66failures introduced by Chromium changes are generally considered P1 and
67`ReleaseBlock-Dev`.
68
69### WebView is often used to show "first-party" content
70
71While many apps do use the WebView to display general web content that's also
72intended to be used in browsers, it's also very common for apps to display what
73the WebView team calls **first-party** (**1P**) content: HTML/CSS/JS which is
74developed specifically for a particular app's WebView, rather than for the open
75web.
76
77The app developer generally considers their 1P content to be part of the app
78itself, whether it's fetched over the network via HTTP(S) at runtime, or loaded
79in an app-specific way. This content can present additional challenges for
80compatibility for several reasons:
81
82* Developers may expect Android's general compatibility rules to apply to all
83 the web platform APIs that their content interacts with, even though this is
84 not the web's usual model.
85
86* Developers may expect their content to be considered just as trustworthy as
87 the rest of their app, so may object to user agent interventions being
88 applied to it; for example, they might expect it to be able to function as
89 normal even if the WebView is in the background or offscreen.
90
91* 1P content is often packaged inside the app binary, dynamically generated,
92 or downloaded from servers that aren't linked to on the open web.
93 * This often makes it "invisible" to search engines, including the HTTP
94 Archive data used by Google as one way to evaluate the compatibility
95 impact of web platform changes, and to Chrome's UMA metrics. Using
96 WebView's own UMA metrics can mitigate this.
97 * This also often makes it slower and more difficult for the developer to
98 fix compatibility issues, since a new version of the app binary may have
99 to be published to the Play Store, and users will not see the changes
100 until they install the app update.
101
102This means that WebView's API surface effectively includes not just the Java
103APIs that apps call to control it, but also the entire web platform, and
104therefore changes to Chromium need not touch any code in `//android_webview` to
105be a risk.
106
107### WebView's metrics and experiments are less mature and comprehensive than Chrome's
108
109WebView does have crash reporting, UMA, and Finch, but in many cases the data is
110noisier, less actionable, or less comprehensive for a number of reasons. This
111can make it harder to rely on data to assess potential compatibility impact.
112
113WebView's beta/dev/canary populations are fairly small and as in Chrome these
114users are a self-selected sample who aren't always representative of the stable
115population. A particular concern for WebView here is that even a fairly popular
116Android app's user base might include significantly fewer pre-stable WebView
117users than the overall population size would suggest; an issue that only affects
118a few specific apps may never be encountered in the field until the stable
119release.
120
121UMA metrics implemented in `//content` (and in those `//components` which are
122shared between WebView and Chrome) are generally already being recorded in
123WebView. UMA metrics implemented in `//chrome` code will not be recorded in
124WebView, and should be moved to lower layers of the code if they're relevant to
125WebView so that they can be shared and compared.
126
127## What are WebView's compatibility goals?
128
129WebView has to strike a balance between allowing the web platform to move
130forward, and ensuring that existing Android apps continue to work correctly.
131Since it's WebView's explicit goal (and on most OS versions, a strict technical
132requirement) to ship new versions alongside Chrome for Android, it's neither
133realistic nor desirable to hold back the vast majority of web platform changes,
134even if they present _some_ compatibility risk. WebView focuses on:
135
136* **Issues that affect a library, framework, or SDK that is used by more than
137 one app developer.** For example: mobile ad SDKs, cross-platform app
138 deployment environments like Cordova, or the AndroidX libraries.
139 * It can take a long time for apps to update to a new library version with
140 the fix, because libraries are almost always compiled into the
141 individual app binaries; Android apps generally can't share library code
142 on-device.
143
144* **Issues where no straightforward fix or workaround can be applied by the
145 app developer.** For example: feature removals, new restrictions, or user
146 agent interventions. If the developer can't realistically update their app
147 to a working state in a short period of time, there's a stronger need for
148 WebView to revert the change or work around the issue on their behalf.
149
150* **Issues that affect common patterns of WebView API usage.** The design
151 choices of WebView's Java APIs often mean that many different apps have
152 similar patterns of usage, either learned from examples on the internet or
153 through natural convergence of implementation; some of these patterns result
154 in `//content` APIs being invoked in ways that Chrome and other browsers do
155 not, and many of them rely on _de facto_ existing behaviour of WebView
156 rather than documented API behaviours. Some are well-known by the WebView
157 team, but others are only discovered after a change is made.
158
159* **Issues that affect very popular apps.** The number of installs of an app
160 roughly has a long-tail distribution, so a very large number of users can be
161 impacted even if just one app is affected by a change.
162
163## What kind of changes are likely to have an effect on WebView compatibility?
164
165### Unusual WebView behaviours
166
167WebView has a number of behaviours and APIs that aren't shared with Chrome or
168other browsers; these can cause unexpected compatibility issues with Chromium
169changes, even if the change is not intended to change web-exposed behaviour.
170Some of the most important examples:
171
172#### URL and origin handling
173
174* WebView allows apps to use any string as a URL scheme, without requiring any
175 definition of which custom schemes are valid.
176 * Requests to URLs with custom schemes trigger normal requests which the
177 app can intercept to provide a response.
178 * The origin of a URL with a custom scheme is just the scheme prefix (e.g.
179 `foo://`), so any URLs with the same custom scheme are considered
180 same-origin.
181 * CORS is expected to work with custom schemes in the same way as with
182 HTTP(S).
183
184* WebView allows apps to load arbitrary content as if it came from an
185 arbitrary URL via
186 [`loadDataWithBaseURL`](https://developer.android.com/reference/android/webkit/WebView#loadDataWithBaseURL(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String)).
187 * The navigation is treated as if it were loading the "base URL", but
188 instead of making a request to that URL, the custom content is loaded as
189 if it were a `data:` URI.
190 * The origin of the loaded page is the origin of the base URL.
191
192* WebView apps frequently use `file://` URLs to load local content; special
193 settings are supported.
194 * The WebView
195 [`setAllowFileAccessFromFileURLs`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs(boolean))
196 API causes all `file://` URLs to be considered same-origin with each
197 other, instead of the default Chrome behaviour of `file://` URLs having
198 an opaque origin.
199 * The WebView
200 [`setAllowUniversalAccessFromFileURLs`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs(boolean))
201 API allows all `file://` URLs to make requests to **any** origin without
202 CORS or any other restrictions.
203 * WebView also supports `content://` URLs to access Android content
204 providers, and these are treated like `file://` URLs in most respects.
205
206#### Process model
207
208* [WebView runs as a library inside the embedding application.](./architecture.md#processes)
209 WebView's browser process is the app's process, and thus any process-global
210 state is potentially shared with the embedding app.
211
212* Depending on the OS version and device configuration, WebView may run in
213 [either "single-process" or "multi-process" mode.](../renderer/README.md)
214 Only one renderer per app is currently used in multi-process mode, but this
215 limit may increase in the future.
216
217* WebView cannot use non-sandboxed child processes regardless of whether it's
218 running in single- or multi- process mode; only sandboxed child processes
219 are supported.
220
221* WebView does not use a separate GPU process even when running in
222 multi-process mode.
223
224#### UI and browser chrome
225
226* WebView doesn't render any UI elements outside of the content viewport. The
227 embedding app is responsible for any UI that may be needed to implement
228 WebView callbacks.
229
230* Callback APIs exist to trigger permission prompts (though apps may not
231 implement them), but there's no current API to render infobars, control how
232 the URL or security status is shown (if at all), or similar features.
233
234* Cooperation from the embedding app is needed to implement features such as
235 popup windows and fullscreen, and apps may not implement these, or implement
236 them incorrectly.
237
238#### Graphics
239
240* WebView's graphics rendering architecture is somewhat different to Chrome's
241 to support specific behaviours apps rely on; see
242 [the architecture doc](https://docs.google.com/document/d/1MLPEmMugdVvfeMeQQN_NMolqs4zZekfKjZeNAQJJnMo)
243 for an overview.
244
245### Issues with existing WebView APIs
246
247#### Permissions
248
249WebView's APIs for allowing the app to control web permissions have significant
250limitations at present. The Web Permissions API is not implemented in WebView,
251and in general any code in Chromium that relies on being able to silently check
252the status of permissions will not work - only actual permission requests are
253supported. This can cause problems when implementing web platform features that
254are gated behind permissions, or when changing the way that existing features
255make permissions checks.
256
257## How do I determine the effect of a change on WebView compatibility?
258
259### CTS
260
261Ensuring that WebView's CTS tests all pass with your change enabled is a very
262important first step; if it causes CTS failures then this means WebView
263compatibility is _definitely_ affected, and means you should definitely
264[reach out to the WebView team](https://groups.google.com/a/chromium.org/forum/#!forum/android-webview-dev)
265to discuss it.
266
267CTS is run as part of the `android-pie-arm64-rel` trybot, and on the main
268waterfall. If your change causes CTS failures, you may need to
269[run CTS locally](./test-instructions.md#cts) to investigate.
270
271### UMA, Finch, and other data collection from the field
272
273WebView has UMA, Finch, and crash reporting, but does not currently have any
274equivalent of UKM. Googlers can read the WebView-specific
275[UMA](http://go/clank-webview-uma) and [Finch](http://go/clank-webview/finch)
276docs for more detailed information, but some key points:
277
278* WebView is a separate "platform" for UMA/Finch purposes; experiments
279 targeting "android" only affect Chrome for Android, _not_ WebView.
280
281* WebView's beta population is fairly small, and its dev and canary
282 populations are tiny. The dev and canary channels are also only available on
283 Android 7 and later, so data from Android 5 and 6 is limited to beta and
284 stable.
285
286* WebView currently uses _per-app_ anonymous IDs for privacy reasons - this
287 means that each individual app on a particular Android device will be
288 considered a "user" or "client" for data collection purposes, with no way
289 to aggregate data at the level of actual users or devices.
290
291* Individual WebView apps can disable metrics collection, even if the user
292 opted in on their device.
293
294* WebView does not always record the package name of the app for privacy
295 reasons.
296
297## My change is likely to (or already did) affect WebView compatibility; what should I do?
298
299There is no single solution here, but there are several common approaches; the
300person(s) making the change should discuss it with the WebView team to decide
301what's appropriate in a particular case. These are not mutually exclusive; it
302may be useful to combine approaches or to move to another approach at a later
303time.
304
305### Apply the change to all apps, but use a Finch experiment for rollout
306
307This is generally the best option if there is some reason to believe that the
308change might be a compatibility issue, but there aren't any specific apps which
309are known to be impacted, and there's no practical way to collect metrics on the
310impact from the field.
311
312You should implement your change behind a flag (if it isn't already), and make
313sure that the flag is **disabled** by default for WebView. You should also
314[expose that flag in WebView's developer UI](./developer-ui.md#Adding-your-flags-and-features-to-the-UI)
315so that testers, app developers, and users can check if their issue is caused by
316your change. On production devices, only the flags in the developer UI can be
317used; it's not possible to pass arbitrary command line flags.
318
319*** aside
320We don't recommend enabling flags by default and relying on "kill switches" in
321Finch for potentially incompatible WebView changes, because WebView apps can't
322apply experiment settings from the server the first time they are launched. This
323means that if an app is broken by your change, it will disproportionately affect
324new users of the app, which is an understandably major concern for app
325developers!
326***
327
328Before enabling the Finch experiment, reach out to the WebView team to discuss
329testing; WebView's QA testers can test popular applications with your flag
330enabled to give you early feedback on potential issues. If there are no issues
331found at this stage, you can proceed with the Finch experiment. Googlers can
332also read
333[the WebView-specific Finch documentation](http://go/clank-webview/finch).
334
335*** note
336If the change causes a WebView CTS test to fail, this is usually not going to be
337an option: existing versions of CTS are expected to pass even with an updated
338version of WebView. Instead, you should work with the WebView team to update the
339_next_ version of CTS, and only apply your change to apps which target the next
340version of Android or later. An exception _may_ be made if the change fixes an
341existing security issue; please discuss this with the WebView team if you think
342it may apply.
343***
344
345### Apply the change to all apps unconditionally
346
347Sometimes it may not be necessary (or reasonable) to use a Finch experiment to
348roll out a change. Some examples of when this may be appropriate:
349
350* if the effect of the change will be immediately obvious to app developers
351 who encounter it, and the appropriate fix is straightforward; e.g. if APIs
352 will now return errors or throw exceptions in cases where they did not
353 before, and the errors provide enough information to address the issue
354
355* if metrics show that the number of affected apps is very small and the issue
356 is rarely encountered
357
358* if the change addresses a security issue
359
360* if the change cannot reasonably be implemented behind a flag for technical
361 reasons
362
363Even in this case, it can still be useful to have a temporary flag to revert to
364the old behaviour, so that testers, app developers, and users can check if their
365issue is caused by the change.
366
367### Reach out to affected apps to ask them to fix the incompatibility
368
369If you are able to determine that only a small number of apps are affected by
370the change, it may be possible to reach out to the developers of those apps and
371suggest changes that will avoid the compatibility issue; you can discuss this
372with the WebView team and we can help. This is more likely to succeed if the
373apps in question are popular and are actively being updated, such that a
374relatively small amount of effort can resolve the issue for a large number of
375users.
376
377You should implement your change behind a flag and
378[expose that flag in WebView's developer UI](./developer-ui.md#Adding-your-flags-and-features-to-the-UI)
379to enable the app developer to test their app with the new behaviour.
380
381You should also ensure that metrics are implemented which will clearly show
382whether apps are still relying on the old behaviour. The metrics you already
383have for the feature may be sufficient, but it may also be useful to add new
384WebView-specific metrics (e.g. to see how relevant WebView Java APIs are being
385used).
386
387Once the flag and metrics are implemented and released (ideally to at least the
388beta channel), the WebView team can help you reach out to the developers in
389question. If the metrics show that the compatibility risk has decreased
390significantly, you can consider rolling the change out via a Finch experiment as
391described above.
392
393### Apply the change to apps that declare targetSdkVersion >= X
394
395This is often applicable when the change is adding a restriction, handling input
396more strictly, or changing the interpretation of currently-accepted but dubious
397or invalid inputs. If apps are using an API incorrectly or ill-advisedly, this
398will allow their existing binaries to continue working, but force them to
399correct their code at some point in the future when they target the new SDK
400version. It also gives us a standard way to communicate the change to
401developers: adding it to the release notes of the next Android version.
402
403The downside is that the old behaviour must still be maintained, either by
404keeping the old code path or by adding explicit compatibility code; both
405versions need to be appropriately tested to avoid future problems, and this can
406eventually become technical debt. You should expect to **maintain both versions
407indefinitely**; we do not currently have a process to sunset target SDK
408compatibility behaviours in WebView.
409
410When making a change conditional on targetSdkVersion, it should only apply to
411Android versions that have yet to be released to developers; once the final
412Android SDK has been released (which happens while the OS update itself is still
413in beta, before the general public release), it's too late to add new
414targetSdkVersion-based requirements. This will often mean that you don't get any
415feedback about how the new behaviour affects WebView for _at least 6-12 months_,
416as apps will still be using the old behaviour for some time.
417
418### Expose a new Java API or setting for apps to control it
419
420If it's reasonable for an app to want to keep the old behaviour in some cases,
421but the new behaviour is also useful/applicable in WebView, then it may be
422desirable to give the app control. This usually either means adding a new
423setting that can be configured through WebView's Java API, or adding a new Java
424callback which apps can implement to make case-by-case decisions.
425
426Where possible, settings should be configurable on a per-WebView basis
427(equivalent to per-tab in Chrome) - apps often use different WebViews for very
428different purposes, and may contain third party libraries that use WebView in a
429manner outside of the app's direct control, so global settings can be difficult
430to use successfully.
431
432WebView's Java API can be extended via the AndroidX compatibility library, which
433is released more frequently than the Android OS, and allows developers to use
434new WebView APIs even on older versions of Android (as long as a new enough
435version of WebView itself is installed on the device).
436
437It's usually necessary for the default to be the _old_ behaviour, and for apps
438to explicitly opt in to the new behaviour. If the new behaviour will usually be
439preferable and the old behaviour is only desired in exceptional cases, one
440option is to make the default conditional on targetSdkVersion (as described in
441the previous section) - default to the old behaviour (with an explicit opt-in to
442the new behaviour) on apps which target <X, and default to the new behaviour
443(with an explicit opt-out to revert to the old behaviour) on apps which target
444>=X.
445
446### Last resort: don't apply the change to WebView at all
447
448This is usually only applicable when it makes sense for the change to be a
449matter of user agent policy, e.g.:
450
451* if it's controlled by a normal user preference in Chrome (**not** by a flag
452 or command line switch)
453
454* if it's controlled by an enterprise policy in Chrome that's not intended to
455 expire in a future release
456
457* if it's explicitly stated to be user agent defined in web specifications
458
459* if other browsers behave differently and aren't going to adopt the same
460 behaviour
461
462This is generally a last resort even if these apply; every place WebView
463entirely diverges from Chrome may become a source of technical debt and other
464issues later. Please talk to the WebView team before deciding to omit WebView
465from a web platform change!
466
467## How do I implement behaviours/options differently in WebView than Chrome?
468
469All code in `//android_webview` is exclusively used in WebView, and no code in
470`//chrome` is ever used by WebView, so if you can make the change at that level,
471it's guaranteed not to affect the other.
472
473In common code (such as `//content` and `//components`), it is **not** possible
474to use `#if` or similar to add/exclude code just for WebView; the distinction
475must be made at runtime. There is also intentionally no generic API or command
476line flag for "is this WebView" (and if you do find something that looks like
477that, please don't use it!) - it should be explicit exactly what
478behaviour/option is being controlled in each case.
479
480*** aside
481All common code is only compiled once for both WebView and Chrome for Android,
482for unavoidable packaging reasons, so there is no `WEBVIEW` or similar macro
483defined. Code can use `#if defined(OS_ANDROID)` to exclude it from other
484platforms if desired, but this includes Chrome for Android.
485***
486
487Mechanisms usually used for this include:
488
489
490* Checking a command line flag in the common code such as
491 `--disable-foo-enforcement`, and setting that flag during WebView's startup,
492 often in [`AwMainDelegate::BasicStartupComplete`](../lib/aw_main_delegate.cc).
493 * This can be used to apply changes conditionally based on the app's
494 targetSdkVersion, or unconditionally for all usage of WebView. Don't use
495 this for settings the app should be able to control.
496 * The command line flag should have a name that describes the actual
497 effect it has, and usually doesn't need to refer to WebView.
498
499* Calling a method defined by the common code from WebView code.
500 * This can be used during startup as a more flexible alternative to a
501 command line flag; for example to easily pass an enum value, or to
502 ensure the change is applied at a specific point in time.
503 * This can also be used when the app should be able to change a global
504 setting at runtime.
505
506* Checking a setting stored in `content::WebPreferences`.
507 * This can be used when the app should be able to change the setting at
508 runtime, usually on a per-WebView basis (e.g. via
509 `android.webkit.WebSettings`).
510
511* Calling a method in a delegate interface defined by the common code and
512 implemented by the WebView/Chrome layer.
513 * This can be used for situations that are more complex than a
514 boolean/enum option, e.g. policy logic with parameters that affect the
515 result, if the policy should be different in Chrome vs WebView.