Richard Coles | f369ba9 | 2020-12-16 21:27:06 | [diff] [blame^] | 1 | # Web platform compatibility in Android WebView |
| 2 | |
| 3 | The Android WebView sometimes needs special consideration and care when making |
| 4 | changes to web platform APIs and behaviours. Chromium developers who make these |
| 5 | changes (especially deliberate interventions) may want to consult this |
| 6 | documentation and/or reach out to the WebView team if they're unsure how a |
| 7 | change 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 | |
| 15 | WebView is part of the Android platform and very widely used in the Android app |
| 16 | ecosystem. Android tries hard to avoid making backward-incompatible changes to |
| 17 | the platform; existing apps (including those the user may have paid for) are |
| 18 | expected to continue to work after an OS update. |
| 19 | |
| 20 | One 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) |
| 22 | in their manifest; this specifies the latest version of the Android SDK that the |
| 23 | developer considered and tested against. Behaviour changes and new restrictions |
| 24 | in the platform are often only applied to apps which target at least the version |
| 25 | in which those changes were introduced; this allows already-published apps to |
| 26 | remain unaffected by the changes. Android's |
| 27 | [release notes](https://developer.android.com/about/versions/10/behavior-changes-10) |
| 28 | for developers call out which changes developers can expect to see when they |
| 29 | update their app's target SDK to the latest version, to make it easier to test |
| 30 | and update apps. |
| 31 | |
| 32 | To avoid apps continuing to target old SDK versions forever (e.g. to permanently |
| 33 | avoid newly introduced restrictions), the Play Store |
| 34 | [enforces a minimum](https://developer.android.com/distribute/best-practices/develop/target-sdk) |
| 35 | when developers upload app binaries to the store: new and updated apps must |
| 36 | target a sufficiently recent version. However, there is no enforcement applied |
| 37 | to existing app binaries: apps that are updated very infrequently or which are |
| 38 | no longer being actively developed at all remain on the store, and may still |
| 39 | target much older SDK versions. This means that the number of apps requiring any |
| 40 | particular piece of backward-compatibility code drops over time, but never to |
| 41 | zero, and in most cases Android retains the backward-compatible code path |
| 42 | indefinitely. |
| 43 | |
| 44 | This means that even though WebView has been receiving frequent updates since |
| 45 | Android 5.0, app developers often still expect that incompatible changes to its |
| 46 | behaviour only happen in new Android releases. |
| 47 | |
| 48 | ### Android's Compatibility Test Suite tests some WebView behaviours |
| 49 | |
| 50 | Android relies on the |
| 51 | [**Compatibility Test Suite** (**CTS**)](https://source.android.com/compatibility/cts) |
| 52 | to ensure that different devices' implementations of Android are compatible with |
| 53 | each other. CTS is versioned alongside the Android OS; any Android 10 device is |
| 54 | expected to pass CTS version 10, and so on. CTS does have minor version updates |
| 55 | to address bugs in the tests themselves, such as flakiness or assumptions that |
| 56 | are discovered not to be valid on all devices; see |
| 57 | [WebView's CTS docs](./tools/cts_config/README.md#changing-cts-tests-retroactively) |
| 58 | for more information on when this may be appropriate. |
| 59 | |
| 60 | CTS contains a number of tests which test the WebView's APIs and behaviours, and |
| 61 | it's expected that these tests will pass even if the device has been updated to |
| 62 | the latest version of WebView. This presents a significant problem for web |
| 63 | platform changes if they cause an existing CTS test to fail; this means WebView |
| 64 | is no longer compatible with that Android version's expectations, and the entire |
| 65 | point of those expectations is that apps may also rely on them. CTS test |
| 66 | failures introduced by Chromium changes are generally considered P1 and |
| 67 | `ReleaseBlock-Dev`. |
| 68 | |
| 69 | ### WebView is often used to show "first-party" content |
| 70 | |
| 71 | While many apps do use the WebView to display general web content that's also |
| 72 | intended to be used in browsers, it's also very common for apps to display what |
| 73 | the WebView team calls **first-party** (**1P**) content: HTML/CSS/JS which is |
| 74 | developed specifically for a particular app's WebView, rather than for the open |
| 75 | web. |
| 76 | |
| 77 | The app developer generally considers their 1P content to be part of the app |
| 78 | itself, whether it's fetched over the network via HTTP(S) at runtime, or loaded |
| 79 | in an app-specific way. This content can present additional challenges for |
| 80 | compatibility 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 | |
| 102 | This means that WebView's API surface effectively includes not just the Java |
| 103 | APIs that apps call to control it, but also the entire web platform, and |
| 104 | therefore changes to Chromium need not touch any code in `//android_webview` to |
| 105 | be a risk. |
| 106 | |
| 107 | ### WebView's metrics and experiments are less mature and comprehensive than Chrome's |
| 108 | |
| 109 | WebView does have crash reporting, UMA, and Finch, but in many cases the data is |
| 110 | noisier, less actionable, or less comprehensive for a number of reasons. This |
| 111 | can make it harder to rely on data to assess potential compatibility impact. |
| 112 | |
| 113 | WebView's beta/dev/canary populations are fairly small and as in Chrome these |
| 114 | users are a self-selected sample who aren't always representative of the stable |
| 115 | population. A particular concern for WebView here is that even a fairly popular |
| 116 | Android app's user base might include significantly fewer pre-stable WebView |
| 117 | users than the overall population size would suggest; an issue that only affects |
| 118 | a few specific apps may never be encountered in the field until the stable |
| 119 | release. |
| 120 | |
| 121 | UMA metrics implemented in `//content` (and in those `//components` which are |
| 122 | shared between WebView and Chrome) are generally already being recorded in |
| 123 | WebView. UMA metrics implemented in `//chrome` code will not be recorded in |
| 124 | WebView, and should be moved to lower layers of the code if they're relevant to |
| 125 | WebView so that they can be shared and compared. |
| 126 | |
| 127 | ## What are WebView's compatibility goals? |
| 128 | |
| 129 | WebView has to strike a balance between allowing the web platform to move |
| 130 | forward, and ensuring that existing Android apps continue to work correctly. |
| 131 | Since it's WebView's explicit goal (and on most OS versions, a strict technical |
| 132 | requirement) to ship new versions alongside Chrome for Android, it's neither |
| 133 | realistic nor desirable to hold back the vast majority of web platform changes, |
| 134 | even 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 | |
| 167 | WebView has a number of behaviours and APIs that aren't shared with Chrome or |
| 168 | other browsers; these can cause unexpected compatibility issues with Chromium |
| 169 | changes, even if the change is not intended to change web-exposed behaviour. |
| 170 | Some 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 | |
| 249 | WebView's APIs for allowing the app to control web permissions have significant |
| 250 | limitations at present. The Web Permissions API is not implemented in WebView, |
| 251 | and in general any code in Chromium that relies on being able to silently check |
| 252 | the status of permissions will not work - only actual permission requests are |
| 253 | supported. This can cause problems when implementing web platform features that |
| 254 | are gated behind permissions, or when changing the way that existing features |
| 255 | make permissions checks. |
| 256 | |
| 257 | ## How do I determine the effect of a change on WebView compatibility? |
| 258 | |
| 259 | ### CTS |
| 260 | |
| 261 | Ensuring that WebView's CTS tests all pass with your change enabled is a very |
| 262 | important first step; if it causes CTS failures then this means WebView |
| 263 | compatibility 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) |
| 265 | to discuss it. |
| 266 | |
| 267 | CTS is run as part of the `android-pie-arm64-rel` trybot, and on the main |
| 268 | waterfall. 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 | |
| 273 | WebView has UMA, Finch, and crash reporting, but does not currently have any |
| 274 | equivalent of UKM. Googlers can read the WebView-specific |
| 275 | [UMA](http://go/clank-webview-uma) and [Finch](http://go/clank-webview/finch) |
| 276 | docs 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 | |
| 299 | There is no single solution here, but there are several common approaches; the |
| 300 | person(s) making the change should discuss it with the WebView team to decide |
| 301 | what's appropriate in a particular case. These are not mutually exclusive; it |
| 302 | may be useful to combine approaches or to move to another approach at a later |
| 303 | time. |
| 304 | |
| 305 | ### Apply the change to all apps, but use a Finch experiment for rollout |
| 306 | |
| 307 | This is generally the best option if there is some reason to believe that the |
| 308 | change might be a compatibility issue, but there aren't any specific apps which |
| 309 | are known to be impacted, and there's no practical way to collect metrics on the |
| 310 | impact from the field. |
| 311 | |
| 312 | You should implement your change behind a flag (if it isn't already), and make |
| 313 | sure 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) |
| 315 | so that testers, app developers, and users can check if their issue is caused by |
| 316 | your change. On production devices, only the flags in the developer UI can be |
| 317 | used; it's not possible to pass arbitrary command line flags. |
| 318 | |
| 319 | *** aside |
| 320 | We don't recommend enabling flags by default and relying on "kill switches" in |
| 321 | Finch for potentially incompatible WebView changes, because WebView apps can't |
| 322 | apply experiment settings from the server the first time they are launched. This |
| 323 | means that if an app is broken by your change, it will disproportionately affect |
| 324 | new users of the app, which is an understandably major concern for app |
| 325 | developers! |
| 326 | *** |
| 327 | |
| 328 | Before enabling the Finch experiment, reach out to the WebView team to discuss |
| 329 | testing; WebView's QA testers can test popular applications with your flag |
| 330 | enabled to give you early feedback on potential issues. If there are no issues |
| 331 | found at this stage, you can proceed with the Finch experiment. Googlers can |
| 332 | also read |
| 333 | [the WebView-specific Finch documentation](http://go/clank-webview/finch). |
| 334 | |
| 335 | *** note |
| 336 | If the change causes a WebView CTS test to fail, this is usually not going to be |
| 337 | an option: existing versions of CTS are expected to pass even with an updated |
| 338 | version 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 |
| 340 | version of Android or later. An exception _may_ be made if the change fixes an |
| 341 | existing security issue; please discuss this with the WebView team if you think |
| 342 | it may apply. |
| 343 | *** |
| 344 | |
| 345 | ### Apply the change to all apps unconditionally |
| 346 | |
| 347 | Sometimes it may not be necessary (or reasonable) to use a Finch experiment to |
| 348 | roll 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 | |
| 363 | Even in this case, it can still be useful to have a temporary flag to revert to |
| 364 | the old behaviour, so that testers, app developers, and users can check if their |
| 365 | issue is caused by the change. |
| 366 | |
| 367 | ### Reach out to affected apps to ask them to fix the incompatibility |
| 368 | |
| 369 | If you are able to determine that only a small number of apps are affected by |
| 370 | the change, it may be possible to reach out to the developers of those apps and |
| 371 | suggest changes that will avoid the compatibility issue; you can discuss this |
| 372 | with the WebView team and we can help. This is more likely to succeed if the |
| 373 | apps in question are popular and are actively being updated, such that a |
| 374 | relatively small amount of effort can resolve the issue for a large number of |
| 375 | users. |
| 376 | |
| 377 | You 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) |
| 379 | to enable the app developer to test their app with the new behaviour. |
| 380 | |
| 381 | You should also ensure that metrics are implemented which will clearly show |
| 382 | whether apps are still relying on the old behaviour. The metrics you already |
| 383 | have for the feature may be sufficient, but it may also be useful to add new |
| 384 | WebView-specific metrics (e.g. to see how relevant WebView Java APIs are being |
| 385 | used). |
| 386 | |
| 387 | Once the flag and metrics are implemented and released (ideally to at least the |
| 388 | beta channel), the WebView team can help you reach out to the developers in |
| 389 | question. If the metrics show that the compatibility risk has decreased |
| 390 | significantly, you can consider rolling the change out via a Finch experiment as |
| 391 | described above. |
| 392 | |
| 393 | ### Apply the change to apps that declare targetSdkVersion >= X |
| 394 | |
| 395 | This is often applicable when the change is adding a restriction, handling input |
| 396 | more strictly, or changing the interpretation of currently-accepted but dubious |
| 397 | or invalid inputs. If apps are using an API incorrectly or ill-advisedly, this |
| 398 | will allow their existing binaries to continue working, but force them to |
| 399 | correct their code at some point in the future when they target the new SDK |
| 400 | version. It also gives us a standard way to communicate the change to |
| 401 | developers: adding it to the release notes of the next Android version. |
| 402 | |
| 403 | The downside is that the old behaviour must still be maintained, either by |
| 404 | keeping the old code path or by adding explicit compatibility code; both |
| 405 | versions need to be appropriately tested to avoid future problems, and this can |
| 406 | eventually become technical debt. You should expect to **maintain both versions |
| 407 | indefinitely**; we do not currently have a process to sunset target SDK |
| 408 | compatibility behaviours in WebView. |
| 409 | |
| 410 | When making a change conditional on targetSdkVersion, it should only apply to |
| 411 | Android versions that have yet to be released to developers; once the final |
| 412 | Android SDK has been released (which happens while the OS update itself is still |
| 413 | in beta, before the general public release), it's too late to add new |
| 414 | targetSdkVersion-based requirements. This will often mean that you don't get any |
| 415 | feedback about how the new behaviour affects WebView for _at least 6-12 months_, |
| 416 | as 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 | |
| 420 | If it's reasonable for an app to want to keep the old behaviour in some cases, |
| 421 | but the new behaviour is also useful/applicable in WebView, then it may be |
| 422 | desirable to give the app control. This usually either means adding a new |
| 423 | setting that can be configured through WebView's Java API, or adding a new Java |
| 424 | callback which apps can implement to make case-by-case decisions. |
| 425 | |
| 426 | Where possible, settings should be configurable on a per-WebView basis |
| 427 | (equivalent to per-tab in Chrome) - apps often use different WebViews for very |
| 428 | different purposes, and may contain third party libraries that use WebView in a |
| 429 | manner outside of the app's direct control, so global settings can be difficult |
| 430 | to use successfully. |
| 431 | |
| 432 | WebView's Java API can be extended via the AndroidX compatibility library, which |
| 433 | is released more frequently than the Android OS, and allows developers to use |
| 434 | new WebView APIs even on older versions of Android (as long as a new enough |
| 435 | version of WebView itself is installed on the device). |
| 436 | |
| 437 | It's usually necessary for the default to be the _old_ behaviour, and for apps |
| 438 | to explicitly opt in to the new behaviour. If the new behaviour will usually be |
| 439 | preferable and the old behaviour is only desired in exceptional cases, one |
| 440 | option is to make the default conditional on targetSdkVersion (as described in |
| 441 | the previous section) - default to the old behaviour (with an explicit opt-in to |
| 442 | the 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 | |
| 448 | This is usually only applicable when it makes sense for the change to be a |
| 449 | matter 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 | |
| 462 | This is generally a last resort even if these apply; every place WebView |
| 463 | entirely diverges from Chrome may become a source of technical debt and other |
| 464 | issues later. Please talk to the WebView team before deciding to omit WebView |
| 465 | from a web platform change! |
| 466 | |
| 467 | ## How do I implement behaviours/options differently in WebView than Chrome? |
| 468 | |
| 469 | All 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, |
| 471 | it's guaranteed not to affect the other. |
| 472 | |
| 473 | In common code (such as `//content` and `//components`), it is **not** possible |
| 474 | to use `#if` or similar to add/exclude code just for WebView; the distinction |
| 475 | must be made at runtime. There is also intentionally no generic API or command |
| 476 | line flag for "is this WebView" (and if you do find something that looks like |
| 477 | that, please don't use it!) - it should be explicit exactly what |
| 478 | behaviour/option is being controlled in each case. |
| 479 | |
| 480 | *** aside |
| 481 | All common code is only compiled once for both WebView and Chrome for Android, |
| 482 | for unavoidable packaging reasons, so there is no `WEBVIEW` or similar macro |
| 483 | defined. Code can use `#if defined(OS_ANDROID)` to exclude it from other |
| 484 | platforms if desired, but this includes Chrome for Android. |
| 485 | *** |
| 486 | |
| 487 | Mechanisms 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. |