0
Files
android_webview
apps
ash
base
build
build_overrides
buildtools
cc
chrome
chromecast
chromeos
codelabs
components
content
courgette
crypto
dbus
device
docs
accessibility
autofill
design
enterprise
experiments
fuchsia
gpu
images
infra
intl
ios
lacros
linux
login
mac
media
memory
memory-infra
patterns
privacy
privacy_budget
process
security
speed
speed_metrics
standards
telemetry_extension
testing
ui
updater
webapps
workflow
DIR_METADATA
OWNERS
README.md
accessibility.md
ad_tagging.md
adding_to_third_party.md
android_accessing_cpp_enums_in_java.md
android_accessing_cpp_features_in_java.md
android_accessing_cpp_switches_in_java.md
android_build_instructions.md
android_cast_build_instructions.md
android_debugging_instructions.md
android_dynamic_feature_modules.md
android_emulator.md
android_isolated_splits.md
android_logging.md
android_native_libraries.md
android_studio.md
angle_in_chromium.md
api_keys.md
asan.md
atom.md
bitmap_pipeline.md
branch_sheriff.md
building_old_revisions.md
callback.md
ccache_mac.md
chrome_os_logging.md
chrome_settings.md
chrome_untrusted.md
chromedriver_status.md
chromeos_build_instructions.md
chromeos_glossary.md
chromium_browser_vs_google_chrome.md
cipd_and_3pp.md
cl_respect.md
clang.md
clang_code_coverage_wrapper.md
clang_format.md
clang_sheriffing.md
clang_static_analyzer.md
clang_tidy.md
clang_tool_refactoring.md
clangd.md
clion.md
closure_compilation.md
cocoa_tips_and_tricks.md
code_review_owners.md
code_reviews.md
commit_checklist.md
component_build.md
configuration.md
contributing.md
cq_quick_run.md
cr_respect.md
cr_user_manual.md
cross_platform_ui.md
cygwin_dll_remapping_failure.md
dangling_ptr.md
dangling_ptr_guide.md
dbus_mojo_connection_service.md
debugging_with_crash_keys.md
deterministic_builds.md
disassemble_code.md
documentation_best_practices.md
documentation_guidelines.md
early-hints.md
eclipse.md
emacs.md
erc_irc.md
flag_expiry.md
flag_guarding_guidelines.md
flag_ownership.md
frame_trees.md
gdbinit.md
get_the_code.md
git_cookbook.md
git_tips.md
google_chrome_branded_builds.md
google_play_services.md
graphical_debugging_aid_chromium_views.md
gwp_asan.md
history_manipulation_intervention.md
how_cc_works.md
how_to_add_your_feature_flag.md
how_to_extend_web_test_framework.md
idn.md
initialize_blink_features.md
inlined_stack_traces.md
installation_at_vmware.md
ios_build_instructions.md
ios_infra.md
ios_voiceover.md
kiosk_mode.md
lacros.md
life_of_a_frame.md
lldbinit.md
mac_arm64.md
mac_build_instructions.md
mac_lld.md
mojo_and_services.md
mojo_ipc_conversion.md
mojo_testing.md
native_relocations.md
navbar.md
navigation-request-navigation-state.gv
navigation-request-navigation-state.png
navigation.md
navigation_concepts.md
network_traffic_annotations.md
no_sources_assignment_filter.md
optimizing_web_uis.md
origin_trials_integration.md
ozone_overview.md
parsing_test_results.md
pgo.md
piranha_plant.md
process_model_and_site_isolation.md
profiling.md
profiling_content_shell_on_android.md
proxy_auto_config.md
python3_migration.md
qtcreator.md
release_branch_guidance.md
render-frame-host-lifecycle-state.gv
render-frame-host-lifecycle-state.png
render_document.md
rust.md
seccomp_sandbox_crash_dumping.md
servicification.md
session_history.md
sheriff.md
shutdown.md
special_case_urls.md
static_initializers.md
sublime_ide.md
system_hardening_features.md
tab_helpers.md
threading_and_tasks.md
threading_and_tasks_faq.md
threading_and_tasks_testing.md
toolchain_support.md
tour_of_luci_ui.md
tpm_quick_ref.md
translation_screenshots.md
trusted_types_on_webui.md
updating_clang.md
updating_clang_format_binaries.md
use_counter_wiki.md
useful_urls.md
user_data_dir.md
user_data_storage.md
user_handle_mapping.md
vanilla_msysgit_workflow.md
vscode.md
vscode_python.md
webui_build_configuration.md
webui_explainer.md
webui_in_chrome.md
webui_in_components.md
webview_policies.md
win_cross.md
win_order_files.md
windows_build_instructions.md
windows_native_window_occlusion_tracking.md
windows_pwa_integration.md
windows_shortcut_and_taskbar_handling.md
windows_split_dll.md
windows_virtual_desktop_handling.md
wmax_tokens.md
working_remotely_with_android.md
writing_clang_plugins.md
extensions
fuchsia_web
gin
google_apis
google_update
gpu
headless
infra
ios
ipc
media
mojo
native_client_sdk
net
pdf
ppapi
printing
remoting
rlz
sandbox
services
skia
sql
storage
styleguide
testing
third_party
tools
ui
url
weblayer
.clang-format
.clang-tidy
.eslintrc.js
.git-blame-ignore-revs
.gitattributes
.gitignore
.gn
.mailmap
.rustfmt.toml
.vpython3
.yapfignore
ATL_OWNERS
AUTHORS
BUILD.gn
CODE_OF_CONDUCT.md
DEPS
DIR_METADATA
LICENSE
LICENSE.chromium_os
OWNERS
PRESUBMIT.py
PRESUBMIT_test.py
PRESUBMIT_test_mocks.py
README.md
WATCHLISTS
codereview.settings
src/docs/windows_pwa_integration.md
John Palmer 046f987e02 [COIL] Change chromium code search type links to use main rather than master for docs
See this doc: go/chromium-coil-change for more info
    BUG=1210385

Change-Id: I6cd8548301e360bae8e71384dbd8ef11aa6c985f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2902904
Reviewed-by: My Nguyen <myy@chromium.org>
Commit-Queue: My Nguyen <myy@chromium.org>
Auto-Submit: John Palmer <jopalmer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#885851}
2021-05-24 01:24:56 +00:00

4.7 KiB

Windows Progressive Web App integration

Desktop Shortcuts

When a Progressive Web App (PWA) is installed on Windows, Chrome creates a desktop shortcut to the PWA, with the PWA icon. The shortcut launches a small Chrome binary chrome_proxy.exe with the app id of the PWA, and the Chrome profile the PWA is installed in. When chrome_proxy.exe runs, it launches Chrome with the same command line options. The shortcut links to chrome_proxy.exe instead of chrome.exe because of a bug in Windows 10 start menu pinning.

File handling support

In order to make Progressive Web Apps (PWA's) more like traditional apps, PWA's support opening files on the user's desktop. On Windows, when a PWA is installed, if the PWA's manifest lists one or more file extension types that it supports opening, Chrome registers the PWA as a handler for the file extension(s), in the Windows registry. When the user right clicks on a file with a registered extension, the PWA name and custom icon appears in the list of applications that can open the file. The user can also set the PWA as the default handler for the file extension.

Because of a limitation of the Windows shell, Chrome registers a per-PWA install launcher app as a handler for the file extension. Chrome ships with a canonical launcher app called chrome_pwa_launcher.exe, which lives in the version sub-directory of the Chrome install dir. When a PWA is installed, we create a hard link from the PWA install dir <profile_dir>/Web Applications/<app_id> to the canonical launcher app. If the hard link fails (e.g., Chrome install dir is on a different drive than the profile dir), we copy the launcher app to the PWA install dir. In either case, the name of the launcher app in the PWA install dir is a sanitized version of the PWA name.

Registration starts in web_app::RegisterFileHandlersWithOS, and works as follows: we create a unique ProgID for the PWA installation with the following format: <BaseAppId>.<hash(Profile + AppID)> We use the hash due to 32-character limit for ProgID's. The registry work is done in ShellUtil::AddFileAssociations:

  • Register the ProgID by adding key HKCU\Software\Classes\<progID> to the registry.
  • Set the application name and icon for the PWA with these two keys:
    • HKCU\Software\Classes\<progID>\Application::ApplicationIcon = <path to icon in PWA install dir>,0
    • HKCU\Software\Classes\<progID>\Application::ApplicationName = <PWA name>
  • Hook up the command to launch the launcher app
    • HKCU\Software\Classes\<progID>\shell\open\command = <launcher_app_path_in_profile> --app-id=<app_id> --profile-directory=<profile_dir>
  • Add a key to keep track of the file extensions registered for a progId, for ease of uninstallation:
    • HKCU\Software\Classes\<progID>\File Extensions = <semicolon delimited list of extensions>

When Chrome is launched, it writes its path into the "Last Browser" file in the User Data dir. When the launcher app is run, it launches Chrome using the path written into the "Last Browser" file. Because the launcher app is in a sub-directory of the profile directory, the "Last Browser" file is in its great grandparent directory.

When a new version of Chrome is installed, we need to update the hard links to and copies of the installed launcher apps to use the newly installed canonical launcher app. This is done by having the launcher app pass its version to Chrome, when launching Chrome. If the launcher app is out of date, Chrome updates all the launcher apps in the current user data dir.

When a PWA is uninstalled, we unregister the PWA as a handler for the file extensions it was registered for. When a PWA changes the file extensions it can handle, we update the registry.

Miscellaneous

  • If the same PWA is registered in multiple profiles, we distinguish them by adding the profile name in parentheses to the PWA name, e.g, "Example PWA (profile1)". If a PWA is uninstalled from a profile, and there is one remaining install in another profile, we remove the profile name from the application name.
  • Windows 7 does not support some of the registry entries needed to set the name and icon for a PWA. So, the file open context menu item for a PWA on Windows 7 gets its name from the launcher app created for the PWA, and uses a generic PWA icon.