[dPWA] Documentation pass

Change-Id: Ib37e5fd25f8c7e6014013cc30285ab3dd5f83a66
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4011202
Reviewed-by: Dibyajyoti Pal <dibyapal@chromium.org>
Reviewed-by: Phillis Tang <phillis@chromium.org>
Commit-Queue: Daniel Murphy <dmurph@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1073071}
diff --git a/chrome/browser/web_applications/README.md b/chrome/browser/web_applications/README.md
index 0ab304c..bae88b1 100644
--- a/chrome/browser/web_applications/README.md
+++ b/chrome/browser/web_applications/README.md
@@ -1,264 +1,4 @@
 # Web Apps
 
-This directory holds the core of Chromium's web app system. For a quick code
-starting point see [WebAppProvider::Start()](web_app_provider.h), this is the
-entry point where everything web app related begins.
-
-
-## What are web apps?
-
-Simply put web apps are sites that the user installs onto their machine
-mimicking a native app install on their respective operating system.
-
-### User entry points
-
-Sites that meet our install promotion requirements will have an install prompt
-appear in the omnibox on the right.
- - Example site: https://developers.google.com/
-Users can also install any site they like via `Menu > More tools > Create
-shortcut...`.
-
-Users can see all of their web apps on chrome://apps (viewable on non-ChromeOS).
-
-### Developer interface
-
-Sites customise how their installed site integrates at the OS level using a
-[web app manifest](https://www.w3.org/TR/appmanifest/).
-See developer guides for in depth overviews:
- - https://web.dev/progressive-web-apps/
- - https://web.dev/codelab-make-installable/
-
-## Terms & Phrases
-
-### Manifest, or WebManifest
-
-This refers to the the document described by the [appmanifest](https://www.w3.org/TR/appmanifest/) spec, with some extra features described by [manifest-incubations](https://wicg.github.io/manifest-incubations/index.html). This document describes metadata and developer configuration of an installable webapp.
-
-For code representations of the manifest see [the list](docs/manifest_representations.md).
-
-### Manifest Link
-
-A manifest link is something that looks like this in a html document:
-```html
-<link rel="manifest" href="manifest.webmanifest">
-```
-This link ties the manifest to the document, and subsequently used in the spec algorithms defined in [appmanifest](https://www.w3.org/TR/appmanifest/) or [manifest-incubations](https://wicg.github.io/manifest-incubations/index.html) to describe the webapp and determine if it is installable.
-
-### Installable
-
-If a document or page is considered "installable", then the user agent can create some form of installed web app for that page. To be installable, [web_app::CanCreateWebApp](https://source.chromium.org/search?q=web_app::CanCreateWebApp) must return true, where:
-* The user profile must allow webapps to be installed
-* The web contents of the page must not be crashed
-* The last navigation on the web contents must not be an error (like a 404)
-* The url must be `http`, `https`, or `chrome-extension`
-
-This is different than [promotable](#promotable) below, which determines if Chrome will promote installation of the page.
-
-### Promotable
-
-A document is considered "promotable" if it fulfils a set of criteria. This criteria may change to further encourage a better user experience for installable web apps. There are also a few optional checks that depend on the promotability checker. This general criteria as of 2021/04/20:
-* The document contains a manifest link.
-* The linked manifest can be [processed](https://www.w3.org/TR/appmanifest/#processing) according to the spec and is valid.
-* The processed manifest contains the fields:
-  * `name`
-  * `start_url`
-  * `icons` with at least one icon with a valid response that is a parsable image.
-  * `display` field that is not `"browser"`
-* "Serviceworker check": The `start_url` is 'controlled' (can be served by) a [serviceworker](https://developers.google.com/web/ilt/pwa/introduction-to-service-worker). **Optionally turned off**
-* "Engagement check": The user has engaged with, or interacted with, the page or origin a certain amount (currently at least one click and some seconds on the site). **Optionally turned off**
-
-Notes:
-* Per spec, the document origin and the `start_url` origin must match.
-* Per spec, the `start_url` origin does not have to match the `manifest_url` origin
-* The `start_url` could be different than the `document_url`.
-
-### Manifest id
-The `id` specified in manifest represents the identity of the web app. The manifest id is processed following the algorithm described in [appmanifest specification](https://www.w3.org/TR/appmanifest/#id-member) to produce the app's identity. In web app system, the app's [identity](https://www.w3.org/TR/appmanifest/#dfn-identity) is [hashed](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/web_app_helpers.cc;l=69;drc=cafa646efbb6f668d3ba20ff482c1f729159ae97) to be stored to [WebApp->app_id()](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/web_app.h;l=43;drc=cafa646efbb6f668d3ba20ff482c1f729159ae97;bpv=1;bpt=1).
-
-The app identity is verified in manifest updating process, if an app gets a manifest with [mismatched identity](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/commands/manifest_update_data_fetch_command.cc;l=265-276), the update process is aborted.
-### Scope
-
-Scope refers to the prefix that a WebApp controls. All paths at or nested inside of a WebApp's scope is thought of as "controlled" or "in-scope" of that WebApp. This is a simple string prefix match. For example, if `scope` is `/my-app`, then the following will be "in-scope":
-* `/my-app/index.html`
-* `/my-app/sub/dir/hello.html`
-* `/my-app-still-prefixed/index.html` (Note: if the scope was `/my-app/`, then this would not be out-of-scope)
-
-And the following will "out-of-scope":
-* `/my-other-app/index.html`
-* `/index.html`
-
-### Display Mode
-
-The `display` of a webapp determines how the developer would like the app to look like to the user. See the [spec](https://www.w3.org/TR/appmanifest/#display-modes) for how the `display` member is processed in the manifest and what the display modes mean.
-
-### User Display Mode
-
-In addition to the developer-specified [`display`](#display-mode), the user can specify how they want a WebApp to be displayed, with the only option being whether to "open in a window" or not. Internally, this is expressed in the same display mode enumeration type as [`display`](#display-mode), but only the `kStandalone` and `kBrowser` values are used to specify "open in a window" and "do not open in a window", respectively.
-
-#### Effective Display Mode
-The psuedocode to determine the ACTUAL display mode a WebApp is displayed is:
-
-```js
-if (user_display_mode == kStandalone)
-  return developer_specified_display_mode;
-else
-  return kBrowser; // Open in a tab.
-```
-
-#### Open-in-window
-This refers to the user specifying that a WebApp should open in the developer specified display mode.
-
-#### Open-in-browser-tab
-This refers to the user specifying that a WebApp should NOT open in a window, and thus the WebApp, if launched, will just be opened in a browser tab.
-
-### Placeholder app
-There are some webapps which are managed by external sources - for example, the enterprise policy force-install apps, or the system web apps for ChromeOS. These are generally not installed by user interaction, and the WebAppProvider needs to install something for each of these apps.
-
-Sometimes, the installation of these apps can fail because the install url is not reachable (usually a cert or login needs to occur, and the url is redirected). When this happens, the system [can](https://source.chromium.org/search?q=ExternalInstallOptions::install_placeholder) install a "placeholder" app, which is a fake application that, when launched navigates to the install url of the application, given by the external app manager.
-
-When any web contents, either in-(placeholder)-app or in the browser, successfully [navigates](https://source.chromium.org/search?q=WebAppTabHelper::ReinstallPlaceholderAppIfNecessary) to a install url that the placeholder app is installed for, the web app installation is restarted for the true app, and after that installation succeeds the placeholder app is uninstalled.
-
-### Locally Installed
-When signing into a non-ChromeOS device, all web apps are installed but not **locally installed**. This means that OS integration is not triggered (so there are no platform shortcuts created), install icons will still show up for the app websites, and the app icon will appear greyed out on chrome://apps.
-
-For an app to become locally installed, the user must do one of the following:
-* Navigate to `chrome://apps`, find the greyed-out icon of the app, right click on it, and select "Install".
-* Follow any of the normal installation routes to install that app (e.g. visit the app page in the browser and interact with the omnibox install icon)
-
-This was done because on non-ChromeOS devices it was considered a bad user experience to fully install all of the profile's web apps (creating platform shortcuts, etc), as this might not be expected by the user.
-
-## What makes up Chromium's implementation?
-
-The task of turning web sites into "apps" in the user's OS environment has many parts to it. Before going into the parts, here is where they live:
-
-[![](docs/webappprovider_component_ownership.jpg)](https://docs.google.com/drawings/d/1TqUF2Pqh2S5qPGyA6njQWxOgSgKQBPePKPIH_srGeRk/edit?usp=sharing)
-
-* The `WebAppProvider` core system lives on the `Profile` object.
-* The `WebAppUiManagerImpl` also lives on the `Profile` object (to avoid deps issues).
-* The `AppBrowserController` (typically `WebAppBrowserController` for our interests) lives on the `Browser` object.
-* The `WebAppTabHelper` lives on the `WebContents` object.
-
-While most on-disk storage is done in the [`WebAppSyncBridge`](#webappsyncbridge), the system also sometimes uses the `PrefService`. Most of these prefs live on the `Profile` (`profile->GetPrefs()`), but some prefs are in the global browser prefs (`g_browser_process->local_state()`). See the [storage](#storage) section below for more info.
-
-There is a presentation that also goes over the class structure and dependency diagram [here](https://docs.google.com/presentation/d/1bJfUFPMh7J_Avw3J4HBvAN2RWnV4T9LOXr0JSAgQAvg/pub), but it may be out of date.
-
-Here is more info for some (but not all) of the key parts:
-
-### [`WebAppProvider`](web_app_provider.h)
-
-This is a per-profile object housing all the various web app subsystems. This is
-the "main()" of the web app implementation where everything starts.
-
-
-### [`WebApp`](web_app.h)
-
-This is the representation of an installed web app in RAM. Its member fields
-largely reflect all the ways a site can configure their
-[web app manifest](https://www.w3.org/TR/appmanifest/) plus miscellaneous
-internal bookkeeping and user settings.
-
-
-### [`WebAppRegistrar`](web_app_registrar.h)
-
-This is where all the [`WebApp`](web_app.h)s live in memory and what many other
-subsystems query to look up any given web app's fields. Mutations to the
-registry have to go via [`WebAppSyncBridge`](web_app_sync_bridge.h).
-
-Why is it full of `GetAppXYZ()` getters for every field instead of just
-returning a `WebApp` reference? Because web apps used to be backed by
-`Extension`s and in that mode there were no `WebApp`s; instead everything was
-stored on an `Extension`.
-
-### [`WebAppSyncBridge`](web_app_sync_bridge.h)
-
-This is "bridge" between the WebAppProvider system's in-memory representation of web apps and the sync system's database representation (along with sync system functionality like add/remove/modify operations). This integration is a little complex and deserves it's own document, but it basically:
-* Stores all WebApps into a database and updates the database if any fields change.
-* Updates the system when there are changes from the sync system.
-  * Installs new apps, uninstalls apps the user uninstalled elsewhere, updates metadata like user display mode preference, etc.
-* Tells the sync system if there are local changes (installs, uninstalls, etc).
-
-There is also a slide in a presentation [here](https://docs.google.com/presentation/d/e/2PACX-1vQxYZoCyhZ4xHS4pVuBC9YoE0O-QpW2Wj3scl6jtr3TEYheeod5Ch4b7OVEQEj_Hc6PM1RBGzovug3C/pub?start=false&loop=false&delayms=3000&slide=id.g59d9cb05b6_6_5) which illustrates how this system works, but it may be out of date.
-
-Note: This only stores per-web-app data, and that data will be deleted if the web app is uninstalled. To store data that persists after uninstall, or applies to a more general scope than a single web app, then the `PrefService` can be used, either on the `Profile` object (per-profile data, `profile->GetPrefs()`) or on the browser process (`g_browser_process->local_state()`). Example of needing prefs:
-* Storing if an app was previously installed as a preinstalled app in the past.
-* Information is needed during chrome startup before profiles are loaded.
-* A feature needs to store global data - e.g. "When was the last time we showed the in-product-help banner for any webapp?"
-
-### [`WebAppInstallManager`](web_app_install_manager.h)
-
-This is where web apps are created, updated and removed. The install manager
-spawns [`WebAppInstallTask`](web_app_install_task.h)s for each "job".
-
-Installation comes in many different forms from a simple "here's all the
-[info](web_app_install_info.h) necessary please install it" to
-"please install the site currently loaded in this web contents and fetch all the
-manifest data it specifies" with a few inbetweens.
-
-
-### [`ExternallyManagedAppManager`](externally_managed_app_manager.h)
-
-This is for all installs that are not initiated by the user. This includes
-[preinstalled apps](preinstalled_web_app_manager.h),
-[policy installed apps](policy/web_app_policy_manager.h) and
-[system web apps](../ash/system_web_apps/system_web_app_manager.h).
-
-These all specify a set of [install URLs](external_install_options.h)
-which the `ExternallyManagedAppManager` synchronises the set of currently
-installed web apps with.
-
-
-### [`WebAppInstallFinalizer`](web_app_install_finalizer.h)
-
-This is the tail end of the installation process where we write all our web app
-metadata to [disk](web_app_database.h) and deploy OS integrations (like
-[desktop shortcuts](web_app_shortcut.h) and
-[file handlers](web_app_file_handler_manager.h)) using the
-[`OsIntegrationManager`](os_integration_manager.h).
-
-This also manages the uninstallation process.
-
-### [`WebAppUiManager`](../ui/web_applications/web_app_ui_manager_impl.h)
-
-Sometimes we need to query window state from chrome/browser/ui land even though
-our BUILD.gn targets disallow this as it would be a circular dependency. This
-[abstract class](web_app_ui_manager.h) + [impl](web_app_ui_manager_impl.h)
-injects the dependency at link time (see
-[`WebAppUiManager::Create()`](https://source.chromium.org/search?q=WebAppUiManager::Create)'s
-declaration and definition locations).
-
-## Storage
-
-TODO
-
-### [`AppShimRegistry`](app_shim_registry_mac.h)
-
-On Mac OS we sometimes need to reason about the state of installed PWAs in all
-profiles without loading those profiles into memory. For this purpose,
-`AppShimRegistry` stores the needed information in Chrome's "Local State"
-(global preferences). The information stored here includes:
-
- * All profiles a particular web app is installed in.
- * What profiles a particular web app was open in when it was last used.
- * What file and protocol handlers are enabled for a web app in each profile
-   it is installed in.
-
-This information is used when launching a web app (to determine what profile
-or profiles to open the web app in), as well as when updating an App Shim
-(to make sure all file and protocol handlers for the app are accounted for).
-
-## Deep Dives
-
-* [Installation Sources & Pipeline](docs/installation_pipeline.md)
-* [Operating system integration](docs/os_integration.md)
-* TODO: Uninstallation
-* TODO: Manifest Update
-
-## Testing
-
-See [the testing docs](docs/testing.md).
-
-## Debugging
-
-Use [chrome://web-app-internals](chrome://web-app-internals) to inspect internal
-web app state. For Chromium versions prior to M93 use
-[chrome://internals/web-app](chrome://internals/web-app).
+Moved to [/docs/webapps/README.md](/docs/webapps/README.md)
+ 
\ No newline at end of file
diff --git a/chrome/browser/web_applications/docs/install_pipeline_2021_04_22.png b/chrome/browser/web_applications/docs/install_pipeline_2021_04_22.png
deleted file mode 100644
index 3f8ebcc..0000000
--- a/chrome/browser/web_applications/docs/install_pipeline_2021_04_22.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/web_applications/docs/installation_pipeline.md b/chrome/browser/web_applications/docs/installation_pipeline.md
deleted file mode 100644
index a5ab9608..0000000
--- a/chrome/browser/web_applications/docs/installation_pipeline.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# [Web Apps](../README.md) - Installation
-
-Installing a webapp can come from a variety of channels. This section serves to enumerate them all and show how they fit together in the installation pipeline. 
-
-Generally, installations all go through the following flow:
-1. Method call in WebAppInstallationManager.
-1. A WebAppInstallTask being queued and run, doing a variety of checks and operations.
-1. A call into WebAppInstallFinalizer, which:
-   1. Triggers any OS integration operations required (creating shortcuts, registering file handlers, etc)
-   1. Saves the WebApp to the database.
-
-The ExternallyManagedAppManager adds a few steps before this, and will sometimes (for placeholder apps) skip the WebAppInstallationManager and directly call into the WebAppInstallFinalizer.
-
-To see a detailed flowchart, see the the [flowchart](#flowchart) below.
-
-## Installation Sources
-
-There are a variety of installation sources and expectations tied to those sources.
-
-### Omnibox install icon
-User-initiated installation. To make the omnibox install icon visible, the document must:
-* Be [promotable](../README.md#promotable) and [installable](../README.md#installable).
-* NOT be inside of the scope of an installed WebApp with an [effective display mode](../README.md#effective-display-mode) display mode that isn't `kBrowser`.
-
-Triggers an install view that will show the name & icon to the user to confirm install.
-
-Calls [`WebAppInstallManager::InstallWebAppFromManifest`](https://source.chromium.org/search?q=function:WebAppInstallManager::InstallWebAppFromManifest), providing just the `WebContents` of the installable page.
-
-Fails if, after the user clicks :
-* After clicking on the install icon, the `WebContents` is no longer [promotable](../README.md#promotable), skipping engagement checks.
-* The user rejects the installation dialog.
-
-
-### 3-dot menu option "Install {App_Name}..."
-User-initiated installation. To make the install menu option visible, the document must:
-* Be [promotable](../README.md#promotable) and [installable](../README.md#installable).
-* NOT be inside of the scope of an installed WebApp with an [effective display mode](../README.md#effective-display-mode) display mode that isn't `kBrowser`.
-
-Triggers an install view that will show the name & icon to the user to confirm install.
-
-Calls [`WebAppInstallManager::InstallWebAppFromManifestWithFallback`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppFromManifestWithFallback) with the `WebContents` of the installable page.
-
-Fails if:
-* The user rejects the installation dialog.
-
-Notably, this option does not go through the same exact pathway as the [omnibox install icon](#omnibox-install-icon), as it shares the call-site as the "Create Shortcut" method below. The main functional difference here is that if the site becomes no longer [promotable](../README.md#promotable) in between clicking on the menu option and the install actually happening, it will not fail and instead fall back to a fake manifest and/or fake icons based on the favicon. Practically, this option doesn't show up if the site is [promotable](../README.md#promotable). Should it share installation pathways as the the [omnibox install icon](#omnibox-install-icon)? Probably, yes.
-
-### 3-dot menu option "Create Shortcut..."
-User-initiated installation. This menu option is always available, except for internal chrome urls like chrome://settings.
-
-Prompts the user whether the shortcut should "open in a window". If the user checks this option, then the resulting WebApp will have the [user display](../README.md#user-display-mode) set to `kStandalone` / open-in-a-window.
-
-The document does not need to have a manifest for this install path to work. If no manifest is found, then a fake one is created with `start_url` equal to the document url, `name` equal to the document title, and the icons are generated from the favicon (if present).
-
-Calls [`WebAppInstallManager::InstallWebAppFromManifestWithFallback`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppFromManifestWithFallback) with the `WebContents` of the page.
-
-Fails if:
-* The user rejects the shortcut creation dialog.
-
-### ChromeOS Management API
-Checks [promotability](../README.md#promotable) before installing, skipping engagement and serviceworker checks
-
-Calls [`WebAppInstallManager::InstallWebAppFromManifest`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppFromManifest), providing just the `WebContents` of the installable page.
-
-TODO: Document when this API is called & why.
-
-### Externally Managed Apps
-There are a number of apps that are managed externally. This means that there is an external manager keeps it's own list of web apps that need to be installed for a given external install source.
-
-See the [`web_app::ExternalInstallSource`](https://source.chromium.org/search?q=web_app::ExternalInstallSource) enum to see all types of externally managed apps. Each source type should have an associated "manager" that gives the list of apps to `ExternallyManagedAppProvider::SynchronizeInstalledApps`.
-
-These installations are customizable than user installations, as these external app management surfaces need to specify all of the options up front (e.g. create shortcut on desktop, open in window, run on login, etc). Thus the install function [`WebAppInstallManager::InstallWebAppWithParams`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppWithParams) is called here, with the params generated by [`web_app::ConvertExternalInstallOptionsToParams`](https://source.chromium.org/search?q=web_app::ConvertExternalInstallOptionsToParams).
-
-The general installation flow of an externally managed app is:
-1. A call to [`ExternallyManagedAppProvider::SynchronizeInstalledApps`](https://source.chromium.org/search?q=ExternallyManagedAppProvider::SynchronizeInstalledApps)
-1. Finding all apps that need to be uninstalled and uninstalling them, find all apps that need to be installed and:
-1. Queue an `ExternallyManagedAppInstallTask` to install each app sequentially.
-1. Each task loads the url for the app.
-1. If the url is successfully loaded, then call [`WebAppInstallManager::InstallWebAppWithParams`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppWithParams), and continue installation on the normal pipeline (described above, and [flowchart](#flowchart) below).
-1. If the url fails to fully load (usually a redirect if the user needs to sign in or corp credentials are not installed), and the external app manager specified a [placeholder app was required](https://source.chromium.org/search?q=ExternalInstallOptions::install_placeholder) then:
-   1. Synthesize a web app with `start_url` as the document url, and `name` as the document title
-   1. Install that webapp using [`WebAppInstallManager::InstallWebAppFromInfo`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppFromInfo). This is **not** part of the regular install pipeline, and basically directly saves the webapp into the database without running OS integration.
-
-These placeholder apps are not meant to stay, and to replace them with the intended apps, the following occurs:
-1. The WebAppProvider system listens to every page load.
-1. If a [navigation is successful](https://source.chromium.org/search?q=WebAppTabHelper::ReinstallPlaceholderAppIfNecessary) to a url that the placeholder app is installed for, then
-   1. The installation is started again with a call to [`WebAppInstallManager::InstallWebAppWithParams`](https://source.chromium.org/search?q=WebAppInstallManager::InstallWebAppWithParams).
-   1. If successful, the placeholder app is uninstalled.
-
-
-### Sync
-
-When the sync system receives an WebApp to install, it calls [`WebAppInstallManager::EnqueueInstallAppFromSync`](https://source.chromium.org/search?q=WebAppInstallManager::EnqueueInstallAppFromSync), which starts the normal installation pipeline. One major difference is if the installation fails for any reason (manifest is invalid or fails to load, etc), then a backup installation happens with a call to [`WebAppInstallTask::InstallWebAppFromInfoRetrieveIcons`](https://source.chromium.org/search?q=WebAppInstallTask::InstallWebAppFromInfoRetrieveIcons). This:
-1. Attempts to get icon data for the install url.
-1. Filters and generates missing icons from the favicon, if there was one.
-1. Calls `WebAppInstallFinalizer` to finalize the install.
-  1. If the platform is not ChromeOS, then the app will not become [locally installed](../README.md#locally-installed). This means that OS integration will not be triggered, no platform shortcuts created, etc.
-  1. If the platform is ChromeOS, it will become [locally installed](../README.md#locally-installed), and all OS integrations will be triggered (just like a normal user-initiated install.)
-
-#### Retry on startup
-Sync installs have a few extra complications:
-* They need to be immediately saved to the database & be installed eventually.
-* Many are often queued up during a new profile sign-in, and it's not uncommon for the user to quit before the installation queue finishes.
-
-Due to this, unlike other installs, a special [`WebApp::is_from_sync_and_pending_installation`](https://source.chromium.org/search?q=WebApp::is_from_sync_and_pending_installation) ([protobuf](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/proto/web_app.proto;l=110;bpv=1;bpt=1?q=web_app.proto%20is_from_sync_and_pending_installation&ss=chromium)) variable is saved in the database. WebApps with this set to true are treated as not fully installed, and are often left out of app listings. This variable is reset back to `false` when the app is finished installing.
-
-To handle the cases above, on startup when the database is loaded, any WebApp with `is_from_sync_and_pending_installation` of `true` will be re-installed inside of [`WebAppSyncBridge::MaybeInstallAppsFromSyncAndPendingInstallation`](https://source.chromium.org/search?q=WebAppSyncBridge::MaybeInstallAppsFromSyncAndPendingInstallation)
-
-## Installation State Modifications
-
-### Installing locally
-On non-ChromeOS devices, an app can be [not locally installed](../README.md#locally-installed). To become locally installed, the user can follow a normal install method (install icon will show up), or they can interact with the app on `chrome://apps`.
-
-The `chrome://apps` code is unique here, and instead of re-installing the app, in manually sets the locally_installed bit to true in [`AppLauncherHandler::HandleInstallAppLocally`](https://source.chromium.org/search?q=AppLauncherHandler::HandleInstallAppLocally), and triggers OS integration in [`AppLauncherHandler::InstallOsHooks`](https://source.chromium.org/search?q=AppLauncherHandler::HandleInstallAppLocally)
-
-### Creating Shortcuts
-Similarly to above, in `chrome://apps` the user can "Create Shortcuts..." for a web app. This should overwrite any shortcuts already created, and basically triggers OS integration to install shortcuts again in [`AppLauncherHandler::HandleCreateAppShortcut`](https://source.chromium.org/search?q=AppLauncherHandler::HandleCreateAppShortcut)
-
-## Flowchart
-
-For reference, this is a flowchart of the installation pipeline as of 2021/04/20: ![Installation pipeline flowchart](install_pipeline_2021_04_22.png)
-Or see https://app.code2flow.com/0JJ8c5nNY4hL for an interactive version.
\ No newline at end of file
diff --git a/docs/webapps/README.md b/docs/webapps/README.md
new file mode 100644
index 0000000..9a20d52
--- /dev/null
+++ b/docs/webapps/README.md
@@ -0,0 +1,357 @@
+## Web Apps
+
+### What are web apps?
+
+Simply put web apps are sites that the user installs onto their machine mimicking a native app installed on their respective operating system.
+
+#### User entry points
+
+Sites that meet our install promotion requirements will have an install prompt appear in the omnibox on the right. Users can also install any site they like via `Menu > More tools > Create shortcut`....
+
+- Example site: https://developers.google.com/
+
+Users can see all of their web apps on chrome://apps (viewable on non-ChromeOS).
+
+#### Developer interface
+
+Sites customize how their installed site integrates at the OS level using a [web app manifest][2]. See developer guides for in depth overviews:
+
+- https://web.dev/progressive-web-apps/
+- https://web.dev/codelab-make-installable/
+
+#### Presentation
+
+See [https://tinyurl.com/dpwa-architecture-public][3] for presentation slides.
+
+### Terms & Phrases
+
+See [Web Apps - Concepts][4].
+
+### Debugging
+
+Use [chrome://web-app-internals][5] to inspect internal web app state. For Chromium versions prior to M93 use [chrome://internals/web-app][6].
+
+### Documentation Guidelines
+
+- Markdown documentation (files like this):
+  - Contains information that can't be documented in class-level documentation.
+  - Answers questions like: What is the goal of a group of classes together? How does a group of classes work together?
+  - Explains concepts that are used across different files.
+  - Should be unlkely to become out-of-date.
+    - Any source links should link to a codesearch 'search' page and not the specific line number.
+    - Avoid implementation details.
+- Class-level documentation (documentation in header files):
+  - Answers questions like: Why does this class exist? What is the responsibility of this class? If this class involves a process with stages, what are those stages / steps?
+  - Should be updated actively when that given file is changed.
+- Documentation inside of methods
+  - Should explain the "why" of code if it is not clear.
+  - Should be avoided otherwise.
+
+### What makes up Chromium's implementation?
+
+The task of turning websites into "apps" in the user's OS environment has many parts to it. Before going into the parts, here is where they live:
+
+![](webappprovider_component_ownership.jpg)
+
+See source [here][7].
+
+- The `WebAppProvider` core system lives on the `Profile` object.
+- The `WebAppUiManagerImpl` also lives on the `Profile` object (to avoid deps issues).
+- The `AppBrowserController` (typically `WebAppBrowserController` for our interests) lives on the `Browser` object.
+- The `WebAppTabHelper` lives on the `WebContents` object.
+
+While most on-disk storage is done in the [`WebAppSyncBridge`][8], the system also sometimes uses the `PrefService`. Most of these prefs live on the `Profile` (`profile->GetPrefs()`), but some prefs are in the global browser prefs (`g_browser_process->local_state()`).
+
+Presentation: [https://tinyurl.com/dpwa-architecture-public][3]
+
+Older presentation: [https://tinyurl.com/bmo-public][9]
+
+### Architecture Philosophy
+
+There are a lot of great guidelines within Chromium
+
+- [Style guides][45]
+- [Dos and Don'ts][47]
+- etc.
+
+Other than general guidance of minimal complexity and having single-responsibility classes, some goals of our system:
+
+- Tests should operate on the [public interface][48] as much as possible. Refactors to the internal system should not involve fixing / modifying tests.
+- [External dependencies][49] should be behind fake-able interfaces, allowing unit & browser tests to swap these out. However, internal parts of our system should not be mocked out or faked - this tightly couples the internal implementation to our tests. If it is impossible to trigger a condition with the public interface, then that condition should be removed (or the public interface improved).
+  - Here is a nice [presentation][44] about testing that might clarify our approach.
+
+### Public Interface
+
+This public interface should (and will) be improved, however this is the basic state as of 2022/11/09:
+
+- `WebAppCommandScheduler`. Internally this schedules `WebAppCommand`s to do safe operations on the system.
+  - This already includes a variety of operations like installation, launching, etc.
+- Observers like the `AppRegistrarObserver` or `WebAppInstallManagerObserver`. However, users of these MUST NOT modify the web app system in the observation call - this can cause race conditions and weird re-entry bugs.
+- Items exposed from the locks given to commands or callbacks:
+  - `WebAppRegistrar`
+  - Writing to the database using `ScopedRegistryUpdate` and the `WebAppSyncBridge`.
+  - Pref reading & writing
+  - etc - see the documentation on the lock for more guidance.
+- `WebAppIconManager` supports icon fetch for a given web app. This isn't yet normally protected in a command / lock, and due to performance needs with things like right-click menus this integration might happen last.
+
+Some parts of the system that are used within commands:
+
+- `WebAppUrlLoader` & `WebAppDataRetriever` are used in commands, but this interface could be improved & does not have a formal factory yet.
+- `WebAppInstallFinalizer` is used in commands and could be improved.
+
+### External Dependencies
+
+The goal is to have all of these behind an abstraction that has a fake to allow easy unit testing of our system. Some of these dependencies are behind a nice fake-able interface, and some are not (yet).
+
+- **Extensions** - Some of our code still talks to the extensions system, specifically the `PreinstalledWebAppManager`.
+- **`content::WebContents`**
+  - **`WebAppUrlLoader`** - load a given url in a `WebContents`. Faked by `FakeWebAppUrlLoader`.
+  - **`WebAppDataRetriever`** - retrieve installability information, the manifest, or icons from a **`WebContents`**. Faked by `FakeWebAppDataRetriever`.
+  - Misc:
+    - Navigation completion in WebAppTabHelper, used to kick off update commands.
+    - Listening to destruction.
+    - IsPrimaryMainFrame() and other filtering.
+    - etc
+- **OS Integration**: Each OS integration has fairly custom code on each OS to do the operation. This is difficult to coordinate and test. Currently the `OsIntegrationManger` manages this, which has a fake version.
+- **Sync system**
+  - There is a tight coupling between our system and the sync system through the WebAppSyncBridge.
+  - Faking this is easy and is handled by the `FakeWebAppProvider`.
+- **UI**: There are parts of the system that are coupled to UI, like showing dialogs, determining information about app windows, etc. These are put behind the `WebAppUiManager`, and faked by the `FakeWebAppUiManager`.
+- **Policy**: Our code depends on the policy system setting it's policies in appropriate prefs for us to read. Because we just look at prefs, we don't need a "fake" here.
+
+### Databases / sources of truth
+
+These store data for our system. Some of it is per-web-app, and some of it is global.
+
+- **`WebAppRegistrar`**: This attempts to unify the reading of much of this data, and also holds an in-memory copy of the database data (in WebApp objects).
+- **`WebAppDatabase`** / **`WebAppSyncBridge`**: This stores the web_app.proto object in a database, which is the preferred place to store information about a web app.
+- **Icons on disk**: These are managed by the `WebAppIconManager` and stored on disk in the user's profile.
+- **Prefs**: The `PrefService` is used to store information that is either global, or needs to persist after a web app is uninstalled. Most of these prefs live on the `Profile` (`profile->GetPrefs()`), but some prefs are in the global browser prefs (`g_browser_process->local_state()`). Some users of prefs:
+  - AppShimRegistry
+  - UserUninstalledPreinstalledWebAppPrefs
+- **OS Integration**: Various OS integration requires storing state on the operating system. Sometimes we are able to read this state back, sometimes not.
+
+None of this information should be accessed without an applicable 'lock' on the system.
+
+### Managers
+
+These are used to encapsulate common responsibilities or in-memory state that needs to be stored.
+
+### Commands
+
+Commands are used to encapsulate operations in the system, and use Locks to ensure that your operation has isolation from other operations.
+
+- If you need to change something in the WebAppProvider system, you should probably use a command.
+- Commands talk to the system using locks they are granted. The locks should offer access to "managers" that the commands can use.
+
+### Locks / `WebAppLockManager`
+
+Locks allow operations to receive appropriate protections for what they are doing. For example, an `AppLock` will guarantee that no one is modifying (or uninstalling) an app while it is granted.
+
+Locks contain assessors that allow the user to access parts of the web app system. This is the safest way to read from the system.
+
+### OS Integration
+
+Anything that involves talking to the operating system. Usually has to do with adding, modifying, or removing the os entity that we register for the web app.
+
+## Deep Dives
+
+- [/docs/webapps/installation_pipeline.md][34]
+- [/docs/webapps/manifest_representations.md][35]
+- [/docs/webapps/integration-testing-framework.md][11]
+- [/docs/webapps/os_integration.md][50]
+- TODO: manifest update
+
+## How To Use
+
+See the [public interface][48] section about which areas are generally "publicly available".
+
+The system is generally unit-test-compabible through the `FakeWebAppProvider`, which is created by default in the `TestingProfile`. Sometimes tests require using the [`AwaitStartWebAppProviderAndSubsystems`][41] function in the setup function of the test to actually start the web app system & wait for it to complete startup.
+
+There is a long-term goal of having the system be easily fake-able for customers using it. The best current 'public interface' distinction of the system is the `WebAppCommandScheduler`, but this hopefully will get more clear in the future.
+
+To access or change information about a web app:
+
+- Obtain a lock from the `WebAppLockManager`, or (preferably) create a command with the relevant lock description.
+- When the lock is obtained (or the command is started with the lock), use the lock to access the data you need.
+  - Generally, you should use the `WebAppRegistrar` to get the data you need. This unifies many of our data sources into one place.
+- If changing data, change the data depending on the source of truth.
+  - For information in the database, use a `ScopedRegistryUpdate`.
+  - Otherwise use the relevant manager / helper to modify the data.
+  - Some things expect "observers" to be notified. That integration is currently in `WebAppSyncBridge`, but can be pulled out.
+
+Other guides:
+
+- [/docs/webapps/why-is-this-test-failing.md][36]
+- [/docs/webapps/how-to-create-webapp-integration-tests.md][37]
+
+## Testing
+
+Please read [Testing In Chromium][42] for general guidance on writing tests in chromium.
+
+The following tests are expected for writing code in this system:
+
+* Unit tests
+* Browser tests
+* Integration tests
+
+### Unit tests
+
+Unit tests have the following benefits:
+
+* They are very efficient.
+* They run on all relevant CQ trybots.
+* They will always be supported by the [code coverage][43] framework.
+
+Unit tests are the fastest tests to execute and are expected to be used to test most cases, especially error cases. They are usually built on the `WebAppTest` base class, and use the `FakeWebAppProvider` to customize (or not) the [dependencies][49] of the `WebAppProvider` system.
+
+Notes
+
+- WebContents and other UI elements do not work in unit tests, and the appropriate fakes must be used (see [External Dependencies][49]).
+- If one of the external dependencies of the system cannot be faked out yet or the feature is tightly coupled to this, then it might make sense to use a browser test instead (or make that dependency fake-able).
+
+### Browser tests
+
+With improved web app test support, most of the components should using unittests to cover the detailed test cases.
+
+Creating an integration test (using the integration framework) should satisfy the need for end-to-end tests for major use-cases of your feature. However, you may need to create one due to:
+
+- The unittest framework doesn’t support certain needs.
+- You need end-to-end test, but using integration test framework has too much overhead in current state.
+
+Browser tests are much more expensive to run, as they basically run a fully functional browser with it's own profile directory. These tests are usually only created to test functionality that requires multiple parts of the system to be running or dependencies like the Sync service to be fully running and functional. It is good practice to have browsertests be as true-to-user-action as possible, to make sure that as much of our stack is exercised.
+
+An example set of browser tests are in [`web_app_browsertest.cc`][38]
+
+### Integration tests
+
+We have a custom integration testing framework that we use due to the complexity of our use-cases. See [integration-testing-framework.md][11] for more information.
+
+**It is a good idea to think about your integration tests early & figure out your CUJs with the team. Having your CUJs and integration tests working early greatly speeds up development & launch time.**
+
+### `Fake*` or `Test*` classes
+
+A class that starts with `Fake` or `Test` is meant to completely replace a component of the system. They should be inheriting from a base class (often pure virtual) and then implement a version of that component that will seem to be working correctly to other system components, but not actually do anything.
+
+An example is [fake_os_integration_manager.h][39], which pretends to successfully do install, update, and uninstall operations, but actually just does nothing.
+
+### `Mock*` classes
+
+A class that start with `Mock` is a [gmock][46] version of the class. This allows the user to have complete control of exactly what that class does, verify it is called exactly as expected, etc. These tend to be much more powerful to use than a `Fake`, as you can easily specify every possible case you might want to check, like which arguments are called and the exact calling order of multiple functions, even across multiple mocks. The downsides are
+* They end up being very verbose to use, often at the expense of test readiability
+* They require creating a mock class & learning how to use gmock.
+
+These are generally not preferred to a "Fake".
+
+### Tool: `FakeWebAppProvider`
+
+The [`FakeWebAppProvider`][40] is basically a fake version of the WebAppProvider system, that uses the  [`WebAppProvider`][12] root class to set up subsystems and can be used to selectively set fake subsystems or shut them
+down on a per-demand basis to test system shutdown use-cases.
+
+### Common issue: External Dependency that isn't faked
+Sometimes classes use a dependency that either doesn't work or isn't fake-able in our system.
+
+1. Can you just not depend on that? The best way is to remove the dependency entirely if possible.
+1. If there is a way to easily fake the dependency that is already supported, then do that next.
+    - e.g. if it's a `KeyedService`, and the authors have a fake version you can use, then use that. See how it is used elsewhere.
+1. Create a new interface for this new external dependency, put it on the `WebAppProvider`, and create a fake for it so that you can test with it faked.
+1. If all else fails, use a browser test.
+
+## Relevant Classes
+
+#### [`WebAppProvider`][12]
+
+This is a per-profile object housing all the various web app subsystems. This is the "main()" of the web app implementation where everything starts.
+
+#### [`WebApp`][13]
+
+This is the representation of an installed web app in RAM. Its member fields largely reflect all the ways a site can configure their [web app manifest][2] plus miscellaneous internal bookkeeping and user settings.
+
+#### [`WebAppRegistrar`][14]
+
+This is where all the [`WebApps`][13] live in memory, and what many other subsystems query to look up any given web app's fields. Mutations to the registry have to go via ScopedRegistryUpdate or [WebAppSyncBridge][16].
+
+Accessing the registrar should happen through a Lock. If you access it through the `WebAppProvider`, then know that you are reading uncommitted (and thus unsafe) data.
+
+Why is it full of `GetAppXYZ()` getters for every field instead of just returning a `WebApp` reference? This is primarily done because the value may depend on multiple sources of truth. For example, whether the app should be run on OS login depends on both the user preference (stored in our database) and the administrator's policy (stored separately & given to us in-memory using prefs) Historically this was originally done because WebApps used be stored both in our database and extensions, and this served to unify the two.
+
+#### [`WebAppSyncBridge`][16]
+
+This is "bridge" between the WebAppProvider system's in-memory representation of web apps and the sync system's database representation (along with sync system functionality like add/remove/modify operations). This integration is a little complex and deserves it's own document, but it basically: _Stores all WebApps into a database and updates the database if any fields change_. Updates the system when there are changes from the sync system. _Installs new apps, uninstalls apps the user uninstalled elsewhere, updates metadata like user display mode preference, etc_. Tells the sync system if there are local changes (installs, uninstalls, etc).
+
+There is also a slide in a presentation [here][18] which illustrates how this system works, but it may be out of date.
+
+Note: This only stores per-web-app data, and that data will be deleted if the web app is uninstalled. To store data that persists after uninstall, or applies to a more general scope than a single web app, then the `PrefService` can be used, either on the `Profile` object (per-profile data, `profile->GetPrefs()`) or on the browser process `(`g_browser_process->local_state()``). Example of needing prefs: Storing if an app was previously installed as a preinstalled app in the past. Information is needed during chrome startup before profiles are loaded. A feature needs to store global data - e.g. "When was the last time we showed the in-product-help banner for any webapp?"
+
+#### [`ExternallyManagedAppManager`][19]
+
+This is for all installs that are not initiated by the user. This includes [preinstalled apps][20], [policy installed apps][21] and [system web apps][22].
+
+These all specify a set of [install URLs][23] which the `ExternallyManagedAppManager` synchronises the set of currently installed web apps with.
+
+#### [`WebAppInstallFinalizer`][24]
+
+This is the tail end of the installation process where we write all our web app metadata to [disk][25] and deploy OS integrations (like [desktop shortcuts][26] and [file handlers][27] using the [`OsIntegrationManager`][28].
+
+This also manages the uninstallation process.
+
+#### [`WebAppUiManager`][29]
+
+Sometimes we need to query window state from chrome/browser/ui land even though our BUILD.gn targets disallow this as it would be a circular dependency. This [abstract class][30] + [impl][31] injects the dependency at link time (see [`WebAppUiManager::Create()`'s`][32] `declaration and definition locations`).
+
+#### [`AppShimRegistry`][33]
+
+On Mac OS we sometimes need to reason about the state of installed PWAs in all profiles without loading those profiles into memory. For this purpose, `AppShimRegistry` stores the needed information in Chrome's "Local State" (global preferences). The information stored here includes:
+
+  - All profiles a particular web app is installed in.
+  - What profiles a particular web app was open in when it was last used.
+  - What file and protocol handlers are enabled for a web app in each profile it is installed in.
+
+This information is used when launching a web app (to determine what profile or profiles to open the web app in), as well as when updating an App Shim (to make sure all file and protocol handlers for the app are accounted for).
+
+[2]: https://www.w3.org/TR/appmanifest/
+[3]: https://tinyurl.com/dpwa-architecture-public
+[4]: concepts.md
+[5]: chrome://web-app-internals
+[6]: chrome://internals/web-app
+[7]: https://docs.google.com/drawings/d/1TqUF2Pqh2S5qPGyA6njQWxOgSgKQBPePKPIH_srGeRk/edit?usp=sharing
+[8]: #webappsyncbridge
+[9]: https://tinyurl.com/bmo-public
+[11]: integration-testing-framework.md
+[12]: /chrome/browser/web_applications/web_app_provider.h
+[13]: /chrome/browser/web_applications/web_app.h
+[14]: /chrome/browser/web_applications/web_app_registrar.h
+[16]: /chrome/browser/web_applications/web_app_sync_bridge.h
+[18]: https://docs.google.com/presentation/d/e/2PACX-1vQxYZoCyhZ4xHS4pVuBC9YoE0O-QpW2Wj3scl6jtr3TEYheeod5Ch4b7OVEQEj_Hc6PM1RBGzovug3C/pub?start=false&loop=false&delayms=3000&slide=id.g59d9cb05b6_6_5
+[19]: /chrome/browser/web_applications/externally_managed_app_manager.h
+[20]: /chrome/browser/web_applications/preinstalled_web_app_manager.h
+[21]: /chrome/browser/web_applications/policy/web_app_policy_manager.h
+[22]: /chrome/browser/ash/system_web_apps/system_web_app_manager.h
+[23]: /chrome/browser/web_applications/external_install_options.h
+[24]: /chrome/browser/web_applications/web_app_install_finalizer.h
+[25]: /chrome/browser/web_applications/web_app_database.h
+[26]: /chrome/browser/web_applications/web_app_shortcut.h
+[27]: /chrome/browser/web_applications/web_app_file_handler_manager.h
+[28]: /chrome/browser/web_applications/os_integration/os_integration_manager.h
+[29]: /chrome/browser/ui/web_applications/web_app_ui_manager_impl.h
+[30]: /chrome/browser/web_applications/web_app_ui_manager.h
+[31]: /chrome/browser/ui/web_applications/web_app_ui_manager_impl.h
+[32]: https://source.chromium.org/search?q=WebAppUiManager::Create
+[33]: /chrome/browser/web_applications/app_shim_registry_mac.h
+[34]: installation_pipeline.md
+[35]: manifest_representations.md
+[36]: why-is-this-test-failing.md
+[37]: how-to-create-webapp-integration-tests.md
+[38]: /chrome/browser/ui/web_applications/web_app_browsertest.cc
+[39]: /chrome/browser/web_applications/test/fake_os_integration_manager.h
+[40]: /chrome/browser/web_applications/test/fake_web_app_provider.h
+[41]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/test/web_app_install_test_utils.cc;l=40?q=AwaitStartWebAppProviderAndSubsystems&ss=chromium
+[42]: ../testing/testing_in_chromium.md
+[43]: ../testing/code_coverage.md
+[44]: https://www.youtube.com/watch?v=EZ05e7EMOLM
+[45]: /styleguide/styleguide.md
+[46]: https://github.com/google/googletest/tree/HEAD/googlemock
+[47]: /styleguide/c++/c++-dos-and-donts.md
+[48]: #public-interface
+[49]: #external-dependencies
+[50]: os-integration.md
diff --git a/docs/webapps/concepts.md b/docs/webapps/concepts.md
new file mode 100644
index 0000000..9442983
--- /dev/null
+++ b/docs/webapps/concepts.md
@@ -0,0 +1,144 @@
+## Web Apps - Concepts
+
+### Manifest, or WebManifest
+
+This refers to the document described by the [appmanifest][2] spec, with some extra features described by [manifest-incubations][3]. This document describes metadata and developer configuration of an installable web app.
+
+For code representations of the manifest see [the list][4].
+
+### Manifest Link
+
+A manifest link is something that looks like this in a html document:
+
+```html
+<link rel="manifest" href="manifest.webmanifest">
+```
+
+This link ties the manifest to the document, and subsequently used in the spec algorithms defined in [appmanifest][2] or [manifest-incubations][3] to describe the webapp and determine if it is installable.
+
+### Installable
+
+If a document or page is considered "installable", then the user agent can create some form of installed web app for that page. To be installable, [web_app::CanCreateWebApp][5] must return true, where:
+
+- The user profile must allow webapps to be installed
+- The web contents of the page must not be crashed
+- The last navigation on the web contents must not be an error (like a 404)
+- The url must be `http, https`, or `chrome-extension`
+
+This is different from [promotable][6] below, which determines if Chrome will promote installation of the page.
+
+### Promotable
+
+A document is considered "promotable" if it fulfills a set of criteria. This criteria may change to further encourage a better user experience for installable web apps. There are also a few optional checks that depend on the promotability checker. This general criteria as of 2022/09/08:
+
+- _The document contains a manifest link_.
+- The linked manifest can be processed [according][7] to the spec and is valid.
+- The processed manifest contains the fields:
+  - `name`
+  - `start_url`
+  - `icons` with at least one icon with a valid response that is a parsable image.
+  - `display` field that is not `"browser`"
+- "Serviceworker check": The `start_url` is 'controlled' (can be served by) a [serviceworker][8] with a fetch handler. **Optionally turned off**
+  - Note: This is expected to be removed in Q4 2022.
+- _"Engagement check": The user has engaged with, or interacted with, the page or origin a certain amount (currently at least one click and some seconds on the site). **Optionally turned off**_
+
+Notes:
+
+- Per spec, the document origin and the `start_url` origin must match.
+- Per spec, the `start_url` origin does not have to match the `manifest_url` origin
+- The `start_url` could be different from the `document_url`.
+
+### Manifest id
+
+The `id` specified in the manifest represents the identity of the web app. The manifest id is processed following the algorithm described in [appmanifest specification][9] to produce the app's identity. In the web app system, the app's [identifier][10] is [hashed][11] to be stored to [WebApp->app_id()][12].
+
+If a manifest is discovered during any sort of page load, then the update process is initiated for that manifest. If it resolves to an `app_id` that is installed, then it will perform an update. See https://web.dev/manifest-updates/ for more information.
+
+### Scope
+
+Scope refers to the prefix that a WebApp controls. All paths at or nested inside of a WebApp's scope are thought of as "controlled" or "in-scope" of that WebApp. This is a simple string prefix match. For example, if `scope` is `/my-app`, then the following will be "in-scope":
+
+- `/my-app/index.html`
+- `/my-app/sub/dir/hello.html`
+- `/my-app-still-prefixed/index.html` (Note: if the scope was `/`, then this would not be out-of-scope)
+
+And the following will be "out-of-scope":
+
+- `/my-other-app/index.html`
+- `/index.html`
+
+### Display Mode
+
+The `display` of a web app determines how the developer would like the app to look like to the user. See the [spec][13] for how the `display` member is processed in the manifest and what the display modes mean.
+
+### User Display Mode
+
+In addition to the developer-specified [`display`][14], the user can specify how they want a WebApp to be displayed, with the only option being whether to "open in a window" or not. Internally, this is expressed in the same display mode enumeration type as [`display`][14], but only the `kStandalone` and `kBrowser` values are used to specify "open in a window" and "do not open in a window", respectively.
+
+#### Effective Display Mode
+
+The pseudocode to determine the ACTUAL display mode a WebApp is displayed is:
+
+```js
+if (user_display_mode == kStandalone)
+  return developer_specified_display_mode;
+else
+  return kBrowser; // Open in a tab.
+```
+
+#### Open-in-window
+
+This refers to the user specifying that a WebApp should open in the developer specified display mode.
+
+#### Open-in-browser-tab
+
+This refers to the user specifying that a WebApp should NOT open in a window, and thus the WebApp, if launched, will just be opened in a browser tab.
+
+### App Management
+
+Each app has one or more 'management source', specified by the [`WebAppManagement`][17] enumeration. This signifies the system that is 'managing' the install, AKA responsible for installing or uninstalling the app. Internally, the web app system will ensure that the app will only be uninstalled if there are no sources left in the app.
+
+When a user installs an app, the `kSync` management source is specified, because user installs are considered 'managed' by the sync system (and installs will by synced to all devices). See the [`WebAppManagement`][17] enumeration for the description of other management sources.
+
+Installation by certain sources can cause the app to no longer be "uninstallable" by the user. The method [`CanUserUninstallWebApp`][18] function determines if this is the case.
+
+#### Placeholder app
+
+There are some webapps which are managed by external sources - for example, the enterprise policy force-install apps, or the system web apps for ChromeOS. These are generally not installed by user interaction, and the WebAppProvider needs to install something for each of these apps.
+
+Sometimes, the installation of these apps can fail because the install url is not reachable (usually a cert or login needs to occur, and the url is redirected). When this happens, the system [can][15] install a "placeholder" app, which is a fake application that, when launched, navigates to the install url of the application, given by the external app manager.
+
+To resolve placeholder apps back into the intended installation, web contents (either in-(placeholder)-app or in the browser) are all listened to. If any web content successfully [navigates][16] to a placeholder app's `install_url`, then:
+
+1. The placeholder app is uninstalled.
+2. After uninstallation, the non-placeholder app is [installed][19].
+
+### Locally Installed
+
+When signing into a non-ChromeOS device, all web apps are installed but not **locally installed**. This means that OS integration is not triggered (so there are no platform shortcuts created), install icons will still show up for the app websites, and the app icon will appear grayed out on chrome://apps.
+
+For an app to become locally installed, the user must do one of the following:
+
+- Navigate to `chrome://apps`, find the grayed-out icon of the app, right click on it, and select "Install".
+- Follow any of the normal installation routes to install that app (e.g. visit the app page in the browser and interact with the omnibox install icon)
+
+This was done because on non-ChromeOS devices it was considered a bad user experience to fully install all of the profile's web apps (creating platform shortcuts, etc), as this might not be expected by the user.
+
+[2]: https://www.w3.org/TR/appmanifest/
+[3]: https://wicg.github.io/manifest-incubations/index.html
+[4]: manifest_representations.md
+[5]: https://source.chromium.org/search?q=web_app::CanCreateWebApp
+[6]: #promotable
+[7]: https://www.w3.org/TR/appmanifest/#processing
+[8]: https://developers.google.com/web/ilt/pwa/introduction-to-service-worker
+[9]: https://www.w3.org/TR/appmanifest/#id-member
+[10]: https://www.w3.org/TR/appmanifest/#dfn-identity
+[11]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/web_app_helpers.cc;l=69;drc=cafa646efbb6f668d3ba20ff482c1f729159ae97
+[12]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/web_app.h;l=43;drc=cafa646efbb6f668d3ba20ff482c1f729159ae97;bpv=1;bpt=1
+[13]: https://www.w3.org/TR/appmanifest/#display-modes
+[14]: #display-mode
+[15]: https://source.chromium.org/search?q=ExternalInstallOptions::install_placeholder
+[16]: https://source.chromium.org/search?q=WebAppTabHelper::ReinstallPlaceholderAppIfNecessary
+[17]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/web_app_constants.h;l=32?q=WebAppManagement&ss=chromium%2Fchromium%2Fsrc
+[18]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/web_app_utils.cc;l=481?q=CanUserUninstallWebApp&ss=chromium%2Fchromium%2Fsrc
+[19]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/externally_managed_app_install_task.cc;l=215?q=OnPlaceholderUninstalled&ss=chromium%2Fchromium%2Fsrc
diff --git a/chrome/browser/web_applications/docs/file_handling.md b/docs/webapps/file_handling.md
similarity index 100%
rename from chrome/browser/web_applications/docs/file_handling.md
rename to docs/webapps/file_handling.md
diff --git a/docs/webapps/how-to-create-webapp-integration-tests.md b/docs/webapps/how-to-create-webapp-integration-tests.md
index d55c40e..f4a7964 100644
--- a/docs/webapps/how-to-create-webapp-integration-tests.md
+++ b/docs/webapps/how-to-create-webapp-integration-tests.md
@@ -73,6 +73,8 @@
 1. Print new tests that need to be manually copied to the integration browsertest files.
 2. Print out test ids that need to be removed.
 
+Note: The option `--delete-in-place` can be used to remove all tests that aren't disabled by sheriffs.
+
 After you make changes to the integration browsertests, please re-run the above command to verify that all of the changes were performed and no mistakes were made. If all looks right, the script will output nothing to console when run a second time.
 
 Possible issues / Things to know:
diff --git a/docs/webapps/installation_pipeline.md b/docs/webapps/installation_pipeline.md
new file mode 100644
index 0000000..7b2e718
--- /dev/null
+++ b/docs/webapps/installation_pipeline.md
@@ -0,0 +1,140 @@
+## [Web Apps][2] - Installation
+
+Installing a webapp can come from a variety of channels. This section serves to enumerate them all and show how they fit together in the installation pipeline.
+
+### Flowchart
+
+Here is a graphic of the installation flow:
+
+![](webapp_installation_process.png)
+
+[https://tinyurl.com/dpwa-installation-flowchart][4]
+
+Note: The ExternallyManagedAppManager adds a few steps before this, and will sometimes (for placeholder apps) build a custom `WebAppInstallInfo` object to skip the 'build' steps.
+
+### Installation Commands
+
+There are a variety of [commands][5] used to install web apps. If introducing a new installation source, consider making a new command to isolate your operation (and prevent it from being complicated by other use-cases).
+
+### Installation Sources
+
+There are a variety of installation sources and expectations tied to those sources.
+
+#### Omnibox install icon
+
+User-initiated installation. To make the omnibox install icon visible, the document must: _Be promotable and installable_. NOT be inside of the scope of an installed WebApp with an effective [display mode display][6] mode that isn't `kBrowser`.
+
+Triggers an install view that will show the name & icon to the user to confirm install. If the manifest also includes screenshots with a wide form-factor, then a more detailed install dialog will be shown.
+
+This uses the [`FetchManifestAndInstallCommand`][7], providing just the `WebContents` of the installable page.
+
+Fails if, after the user clicks : _After clicking on the install icon, the `WebContents` is no longer_ [_promotable_][8], _skipping engagement checks_. The user rejects the installation dialog.
+
+#### 3-dot menu option "Install {App_Name}..."
+
+User-initiated installation. To make the install menu option visible, the document must: _Be promotable and installable_. NOT be inside of the scope of an installed WebApp with an effective [display mode display][6] mode that isn't `kBrowser`.
+
+Triggers an install view that will show the name & icon to the user to confirm install. If the manifest also includes screenshots with a wide form-factor, then a more detailed install dialog will be shown.
+
+Calls [`FetchManifestAndInstallCommand`][7] with the `WebContents` of the installable page, and `use_fallback = true`.
+
+Fails if: _The user rejects the installation dialog_.
+
+Notably, this option does not go through the same exact pathway as the [omnibox install icon][10], as it shares the call-site as the "Create Shortcut" method below. The main functional difference here is that if the site becomes no longer [promotable][8] in between clicking on the menu option and the install actually happening, it will not fail and instead fall back to a fake manifest and/or fake icons based on the favicon. Practically, this option doesn't show up if the site is [promotable][8]. Should it share installation pathways as the the [omnibox install icon?][10] Probably, yes.
+
+#### 3-dot menu option "Create Shortcut..."
+
+User-initiated installation. This menu option is always available, except for internal chrome urls like chrome://settings.
+
+Prompts the user whether the shortcut should "open in a window". If the user checks this option, then the resulting WebApp will have the [user display][11] set to `kStandalone` / open-in-a-window.
+
+The document does not need to have a manifest for this install path to work. If no manifest is found, then a fake one is created with `start_url` equal to the document url, `name` equal to the document title, and the icons are generated from the favicon (if present).
+
+Calls [`FetchManifestAndInstallCommand`][7] with the `WebContents` of the installable page, and `use_fallback = true`.
+
+Fails if: _The user rejects the shortcut creation dialog_.
+
+#### ChromeOS Management API
+
+Checks [promotability][8] before installing, skipping engagement and serviceworker checks
+
+Calls [`WebAppInstallManager::InstallWebAppFromManifest`][12], providing just the `WebContents` of the installable page.
+
+TODO: Document when this API is called & why.
+
+#### Externally Managed Apps
+
+There are a number of apps that are managed externally. This means that there is an external manager keeps it's own list of web apps that need to be installed for a given external install source.
+
+See the [`web_app::ExternalInstallSource`][13] enum to see all types of externally managed apps. Each source type should have an associated "manager" that gives the list of apps to `ExternallyManagedAppProvider::SynchronizeInstalledApps`.
+
+These installations are customizable than user installations, as these external app management surfaces need to specify all of the options up front (e.g. create shortcut on desktop, open in window, run on login, etc). Thus the [`ExternallyManagedInstallCommand`][14] is called here, with the params generated by [`web_app::ConvertExternalInstallOptionsToParams`][15].
+
+The general installation flow of an externally managed app is:
+
+1. A call to [`ExternallyManagedAppProvider::SynchronizeInstalledApps`][16]
+1. Finding all apps that need to be uninstalled and uninstalling them, find all apps that need to be installed and:
+1. Queue an `ExternallyManagedAppInstallTask` to install each app sequentially.
+1. Each task loads the url for the app.
+1. If the url is successfully loaded, then use [`ExternallyManagedInstallCommand`][14], and continue installation on the normal pipeline (described above, and [flowchart][17] above).
+1. If the url fails to fully load (usually a redirect if the user needs to sign in or corp credentials are not installed), and the external app manager specified a [placeholder app was required][18] then:
+    1. Synthesize a web app with `start_url` as the document url, and `name` as the document title
+    1. Install that webapp by using the finalizer directly. This is **not** part of the regular install pipeline, and basically directly saves the webapp into the database without running OS integration.
+
+These placeholder apps are not meant to stay, and to replace them with the intended apps, the following occurs:
+
+1. The WebAppProvider system listens to every page load.
+1. If a [navigation is successful][20] to a url that the placeholder app is installed for, then
+    1. The installation is started again with a call to [`WebAppInstallManager::InstallWebAppWithParams`][14].
+    1. If successful, the placeholder app is uninstalled.
+
+#### Sync
+
+When the sync system receives an WebApp to install, it uses the [InstallFromSyncCommand`][21]. One major difference is if the installation fails for any reason (manifest is invalid or fails to load, etc), then a backup installation happens using information from the icon urls from the sync data, and document/favicons if available.
+
+If the platform is not ChromeOS, then the app will not become [locally installed][23]. This means that OS integration will not be triggered, no platform shortcuts created, etc. 1. If the platform is ChromeOS, it will become [locally installed][23], and all OS integrations will be triggered (just like a normal user-initiated install.)
+
+##### Retry on startup
+
+Sync installs have a few extra complications:
+
+- They need to be immediately saved to the database & be installed eventually.
+- Many are often queued up during a new profile sign-in, and it's not uncommon for the user to quit before the installation queue finishes.
+
+Due to this, unlike other installs, a special [`WebApp::is_from_sync_and_pending_installation`][24] (protobuf variable is saved in the database. WebApps with this set to true are treated as not fully installed, and are often left out of app listings. This variable is reset back to `false` when the app is finished installing.
+
+To handle the cases above, on startup when the database is loaded, any WebApp with `is_from_sync_and_pending_installation` of `true` will be re-installed inside of [`WebAppSyncBridge::MaybeInstallAppsFromSyncAndPendingInstallation`][25]
+
+### Installation State Modifications
+
+#### Installing locally
+
+On non-ChromeOS devices, an app can be [not locally installed][23]. To become locally installed, the user can follow a normal install method (install icon will show up), or they can interact with the app on `chrome://apps`.
+
+The `chrome://apps` code is unique here, and instead of re-installing the app, in manually sets the locally_installed bit to true in [`AppLauncherHandler::HandleInstallAppLocally`][26], and triggers OS integration in [`AppLauncherHandler::InstallOsHooks`][26]
+
+#### Creating Shortcuts
+
+Similarly to above, in `chrome://apps` the user can "Create Shortcuts..." for a web app. This should overwrite any shortcuts already created, and basically triggers OS integration to install shortcuts again in [`AppLauncherHandler::HandleCreateAppShortcut`][27]
+
+[2]: README.md
+[4]: https://tinyurl.com/dpwa-installation-flowchart
+[5]: https://source.chromium.org/search?q=f:install%20f:web_applications%2Fcommands&sq=&ss=chromium
+[6]: concepts.md#effective-display-mode
+[7]: https://source.chromium.org/search?q=FetchManifestAndInstallCommand&ss=chromium
+[8]: concepts.md#promotable
+[10]: #omnibox-install-icon
+[11]: concepts.md#user-display-mode
+[13]: https://source.chromium.org/search?q=web_app::ExternalInstallSource
+[14]: https://source.chromium.org/search?q=ExternallyManagedInstallCommand&sq=&ss=chromium%2Fchromium%2Fsrc
+[15]: https://source.chromium.org/search?q=web_app::ConvertExternalInstallOptionsToParams
+[16]: https://source.chromium.org/search?q=ExternallyManagedAppProvider::SynchronizeInstalledApps
+[17]: #flowchart
+[18]: https://source.chromium.org/search?q=ExternalInstallOptions::install_placeholder
+[20]: https://source.chromium.org/search?q=WebAppTabHelper::ReinstallPlaceholderAppIfNecessary
+[21]: https://source.chromium.org/search?q=InstallFromSyncCommand&ss=chromium%2Fchromium%2Fsrc
+[23]: ../README.md#locally-installed
+[24]: https://source.chromium.org/search?q=WebApp::is_from_sync_and_pending_installation
+[25]: https://source.chromium.org/search?q=WebAppSyncBridge::MaybeInstallAppsFromSyncAndPendingInstallation
+[26]: https://source.chromium.org/search?q=AppLauncherHandler::HandleInstallAppLocally
+[27]: https://source.chromium.org/search?q=AppLauncherHandler::HandleCreateAppShortcut
\ No newline at end of file
diff --git a/chrome/browser/web_applications/docs/manifest_representations.md b/docs/webapps/manifest_representations.md
similarity index 100%
rename from chrome/browser/web_applications/docs/manifest_representations.md
rename to docs/webapps/manifest_representations.md
diff --git a/chrome/browser/web_applications/docs/os_integration.md b/docs/webapps/os_integration.md
similarity index 87%
rename from chrome/browser/web_applications/docs/os_integration.md
rename to docs/webapps/os_integration.md
index 9b67fac9..b34e19c 100644
--- a/chrome/browser/web_applications/docs/os_integration.md
+++ b/docs/webapps/os_integration.md
@@ -1,13 +1,13 @@
-# [Web Apps](../README.md) - Operating System Integration
+# [Web Apps](README.md) - Operating System Integration
 
-The WebAppProvider system has to provide a lot of integrations with operating system surfaces for web apps. This functionality is usually different per operating system, and is usually invoked through the [`OsIntegrationManager`](../os_integration_manager.h).
+The WebAppProvider system has to provide a lot of integrations with operating system surfaces for web apps. This functionality is usually different per operating system, and is usually invoked through the [`OsIntegrationManager`][2].
 
-The [`OsIntegrationManager`](../os_integration_manager.h)'s main responsibility is support the following operations:
+The [`OsIntegrationManager`][2]'s main responsibility is support the following operations:
 1. Install operating system integration for a given web app.
 1. Update operating system integration for a given web app.
 1. Uninstall/remove operating system integration for a given web app.
 
-It owns sub-managers who are responsible for each individual operating system integration functionality (e.g. [`web_app_file_handler_manager.h`](../web_app_file_handler_manager.h) which owns the file handling feature). That manager will implement the non-os-specific logic, and then call into functions that have os-specific implementations (e.g. `web_app_file_handler_registration.h/_mac.h/_win.h/_linux.h` files).
+It owns sub-managers who are responsible for each individual operating system integration functionality (e.g. [`web_app_file_handler_manager.h`][1] which owns the file handling feature). That manager will implement the non-os-specific logic, and then call into functions that have os-specific implementations (e.g. `web_app_file_handler_registration.h/_mac.h/_win.h/_linux.h` files).
 
 Below are sections describing how each OS integration works.
 
@@ -93,3 +93,5 @@
 needs to be updated with a profile specific name and executes required update.
 
 
+[1]: /chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
+[2]: /chrome/browser/web_applications/os_integration/os_integration_manager.h
\ No newline at end of file
diff --git a/chrome/browser/web_applications/docs/signed_web_bundle_parser_class_structure.png b/docs/webapps/signed_web_bundle_parser_class_structure.png
similarity index 100%
rename from chrome/browser/web_applications/docs/signed_web_bundle_parser_class_structure.png
rename to docs/webapps/signed_web_bundle_parser_class_structure.png
Binary files differ
diff --git a/chrome/browser/web_applications/docs/testing.md b/docs/webapps/testing.md
similarity index 100%
rename from chrome/browser/web_applications/docs/testing.md
rename to docs/webapps/testing.md
diff --git a/docs/webapps/webapp_installation_process.png b/docs/webapps/webapp_installation_process.png
new file mode 100644
index 0000000..79e6387
--- /dev/null
+++ b/docs/webapps/webapp_installation_process.png
Binary files differ
diff --git a/chrome/browser/web_applications/docs/webappprovider_component_ownership.jpg b/docs/webapps/webappprovider_component_ownership.jpg
similarity index 100%
rename from chrome/browser/web_applications/docs/webappprovider_component_ownership.jpg
rename to docs/webapps/webappprovider_component_ownership.jpg
Binary files differ