WebApp: record both application and user preference for display mode

We persist both the app's preference and the user's preference for
the display mode.

The user's preference (open in Browser tab or in Standalone window) was already being stored and synced.
This field is renamed as user_display_mode.

We now additionally store the app's preference, as display_mode. Note it is only stored locally, not synced.

Not yet implemented: recording app's preferred display mode
in the extensions-based implementation of bookmark apps -
crbug.com/1014346

[email protected]

Bug: 1014347, 1013968
Change-Id: Icab31053e40761194f62e961e3317acea655bca6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1882197
Commit-Queue: Eric Willigers <[email protected]>
Reviewed-by: Marc Treib <[email protected]>
Reviewed-by: Alan Cutter <[email protected]>
Reviewed-by: Alexey Baskakov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#710294}
diff --git a/chrome/browser/web_applications/components/app_registrar.h b/chrome/browser/web_applications/components/app_registrar.h
index e07758d..7a21810 100644
--- a/chrome/browser/web_applications/components/app_registrar.h
+++ b/chrome/browser/web_applications/components/app_registrar.h
@@ -78,7 +78,7 @@
       const AppId& app_id) const = 0;
   virtual const GURL& GetAppLaunchURL(const AppId& app_id) const = 0;
   virtual base::Optional<GURL> GetAppScope(const AppId& app_id) const = 0;
-  virtual blink::mojom::DisplayMode GetAppDisplayMode(
+  virtual blink::mojom::DisplayMode GetAppUserDisplayMode(
       const web_app::AppId& app_id) const = 0;
 
   virtual std::vector<AppId> GetAppIds() const = 0;
diff --git a/chrome/browser/web_applications/components/app_registry_controller.h b/chrome/browser/web_applications/components/app_registry_controller.h
index 7f61c94..8639231 100644
--- a/chrome/browser/web_applications/components/app_registry_controller.h
+++ b/chrome/browser/web_applications/components/app_registry_controller.h
@@ -33,8 +33,9 @@
 
   virtual void Init(base::OnceClosure callback) = 0;
 
-  virtual void SetAppDisplayMode(const AppId& app_id,
-                                 blink::mojom::DisplayMode display_mode) = 0;
+  virtual void SetAppUserDisplayMode(
+      const AppId& app_id,
+      blink::mojom::DisplayMode display_mode) = 0;
 
   virtual void SetAppIsLocallyInstalledForTesting(
       const AppId& app_id,
diff --git a/chrome/browser/web_applications/components/external_install_options.cc b/chrome/browser/web_applications/components/external_install_options.cc
index 2dd6f58..4e9da870 100644
--- a/chrome/browser/web_applications/components/external_install_options.cc
+++ b/chrome/browser/web_applications/components/external_install_options.cc
@@ -14,9 +14,11 @@
 
 ExternalInstallOptions::ExternalInstallOptions(
     const GURL& url,
-    blink::mojom::DisplayMode display_mode,
+    blink::mojom::DisplayMode user_display_mode,
     ExternalInstallSource install_source)
-    : url(url), display_mode(display_mode), install_source(install_source) {}
+    : url(url),
+      user_display_mode(user_display_mode),
+      install_source(install_source) {}
 
 ExternalInstallOptions::~ExternalInstallOptions() = default;
 
@@ -31,13 +33,13 @@
 
 bool ExternalInstallOptions::operator==(
     const ExternalInstallOptions& other) const {
-  return std::tie(url, display_mode, install_source, add_to_applications_menu,
-                  add_to_desktop, add_to_quick_launch_bar,
-                  override_previous_user_uninstall, bypass_service_worker_check,
-                  require_manifest, force_reinstall, wait_for_windows_closed,
-                  install_placeholder, reinstall_placeholder,
-                  uninstall_and_replace) ==
-         std::tie(other.url, other.display_mode, other.install_source,
+  return std::tie(url, user_display_mode, install_source,
+                  add_to_applications_menu, add_to_desktop,
+                  add_to_quick_launch_bar, override_previous_user_uninstall,
+                  bypass_service_worker_check, require_manifest,
+                  force_reinstall, wait_for_windows_closed, install_placeholder,
+                  reinstall_placeholder, uninstall_and_replace) ==
+         std::tie(other.url, other.user_display_mode, other.install_source,
                   other.add_to_applications_menu, other.add_to_desktop,
                   other.add_to_quick_launch_bar,
                   other.override_previous_user_uninstall,
@@ -49,8 +51,8 @@
 
 std::ostream& operator<<(std::ostream& out,
                          const ExternalInstallOptions& install_options) {
-  return out << "url: " << install_options.url << "\n display_mode: "
-             << static_cast<int32_t>(install_options.display_mode)
+  return out << "url: " << install_options.url << "\n user_display_mode: "
+             << static_cast<int32_t>(install_options.user_display_mode)
              << "\n install_source: "
              << static_cast<int32_t>(install_options.install_source)
              << "\n add_to_applications_menu: "
@@ -78,7 +80,7 @@
     const ExternalInstallOptions& install_options) {
   InstallManager::InstallParams params;
 
-  params.display_mode = install_options.display_mode;
+  params.user_display_mode = install_options.user_display_mode;
 
   params.add_to_applications_menu = install_options.add_to_applications_menu;
   params.add_to_desktop = install_options.add_to_desktop;
diff --git a/chrome/browser/web_applications/components/external_install_options.h b/chrome/browser/web_applications/components/external_install_options.h
index d0af92fb..b742eccf 100644
--- a/chrome/browser/web_applications/components/external_install_options.h
+++ b/chrome/browser/web_applications/components/external_install_options.h
@@ -18,7 +18,7 @@
 
 struct ExternalInstallOptions {
   ExternalInstallOptions(const GURL& url,
-                         blink::mojom::DisplayMode display_mode,
+                         blink::mojom::DisplayMode user_display_mode,
                          ExternalInstallSource install_source);
   ~ExternalInstallOptions();
   ExternalInstallOptions(const ExternalInstallOptions& other);
@@ -28,7 +28,7 @@
   bool operator==(const ExternalInstallOptions& other) const;
 
   GURL url;
-  blink::mojom::DisplayMode display_mode;
+  blink::mojom::DisplayMode user_display_mode;
   ExternalInstallSource install_source;
 
   // If true, a shortcut is added to the Applications folder on macOS, and Start
diff --git a/chrome/browser/web_applications/components/install_finalizer.cc b/chrome/browser/web_applications/components/install_finalizer.cc
index b7a79bb9..076cfba6f 100644
--- a/chrome/browser/web_applications/components/install_finalizer.cc
+++ b/chrome/browser/web_applications/components/install_finalizer.cc
@@ -30,7 +30,7 @@
   // Reparent the web contents into its own window only if that is the
   // app's launch type.
   DCHECK(registrar_);
-  if (registrar_->GetAppDisplayMode(app_id) !=
+  if (registrar_->GetAppUserDisplayMode(app_id) !=
       blink::mojom::DisplayMode::kStandalone)
     return false;
 
diff --git a/chrome/browser/web_applications/components/install_manager.h b/chrome/browser/web_applications/components/install_manager.h
index 6a0e503a..ced10c59 100644
--- a/chrome/browser/web_applications/components/install_manager.h
+++ b/chrome/browser/web_applications/components/install_manager.h
@@ -89,7 +89,7 @@
 
   // These params are a subset of ExternalInstallOptions.
   struct InstallParams {
-    blink::mojom::DisplayMode display_mode =
+    blink::mojom::DisplayMode user_display_mode =
         blink::mojom::DisplayMode::kUndefined;
 
     bool add_to_applications_menu = true;
diff --git a/chrome/browser/web_applications/components/manifest_update_task.cc b/chrome/browser/web_applications/components/manifest_update_task.cc
index 3641d501..949b534b 100644
--- a/chrome/browser/web_applications/components/manifest_update_task.cc
+++ b/chrome/browser/web_applications/components/manifest_update_task.cc
@@ -122,17 +122,17 @@
   web_application_info->title =
       base::UTF8ToUTF16(registrar_.GetAppShortName(app_id_));
 
-  // Preserve the user's choice of launch container (excluding fullscreen).
-  switch (registrar_.GetAppDisplayMode(app_id_)) {
+  // Preserve the user's choice of opening in browser tab or standalone window.
+  switch (registrar_.GetAppUserDisplayMode(app_id_)) {
     case blink::mojom::DisplayMode::kBrowser:
       web_application_info->open_as_window = false;
       break;
-    case blink::mojom::DisplayMode::kMinimalUi:
     case blink::mojom::DisplayMode::kStandalone:
-    case blink::mojom::DisplayMode::kFullscreen:
       web_application_info->open_as_window = true;
       break;
     case blink::mojom::DisplayMode::kUndefined:
+    case blink::mojom::DisplayMode::kMinimalUi:
+    case blink::mojom::DisplayMode::kFullscreen:
       NOTREACHED();
       break;
   }
diff --git a/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc
index a2c9ede..a54d2d7 100644
--- a/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc
+++ b/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc
@@ -42,19 +42,18 @@
          default_launch_container->GetString() ==
              kDefaultLaunchContainerTabValue);
 
-  blink::mojom::DisplayMode display_mode;
+  blink::mojom::DisplayMode user_display_mode;
   if (!default_launch_container) {
-    display_mode = blink::mojom::DisplayMode::kBrowser;
+    user_display_mode = blink::mojom::DisplayMode::kBrowser;
   } else if (default_launch_container->GetString() ==
              kDefaultLaunchContainerTabValue) {
-    display_mode = blink::mojom::DisplayMode::kBrowser;
+    user_display_mode = blink::mojom::DisplayMode::kBrowser;
   } else {
-    // TODO(crbug.com/1009909): Support Minimal UI.
-    display_mode = blink::mojom::DisplayMode::kStandalone;
+    user_display_mode = blink::mojom::DisplayMode::kStandalone;
   }
 
   ExternalInstallOptions install_options{
-      GURL(url.GetString()), display_mode,
+      GURL(url.GetString()), user_display_mode,
       ExternalInstallSource::kExternalPolicy};
 
   install_options.add_to_applications_menu = true;
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc
index 1f6bcc3..14f68eda 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/web_applications/components/web_app_icon_generator.h"
 #include "chrome/common/web_application_info.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 namespace web_app {
@@ -126,6 +127,14 @@
   if (manifest.theme_color)
     web_app_info->theme_color = *manifest.theme_color;
 
+  // When the display member is missing, or if there is no valid display member,
+  // the user agent uses the browser display mode as the default display mode.
+  // https://w3c.github.io/manifest/#display-modes
+  web_app_info->display_mode =
+      (manifest.display == blink::mojom::DisplayMode::kUndefined)
+          ? blink::mojom::DisplayMode::kBrowser
+          : manifest.display;
+
   // Create the WebApplicationInfo icons list *outside* of |web_app_info|, so
   // that we can decide later whether or not to replace the existing icons array
   // (conditionally on whether there were any that didn't have purpose ANY).
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
index fabd63de..9064648 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -8,6 +8,7 @@
 #include "chrome/common/web_application_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "url/gurl.h"
 
 namespace web_app {
@@ -51,6 +52,7 @@
                                ForInstallableSite::kNo);
   EXPECT_EQ(base::UTF8ToUTF16(kAppShortName), web_app_info.title);
   EXPECT_EQ(kAppUrl, web_app_info.app_url);
+  EXPECT_EQ(blink::mojom::DisplayMode::kBrowser, web_app_info.display_mode);
 
   // The icon info from |web_app_info| should be left as is, since the manifest
   // doesn't have any icon information.
@@ -60,6 +62,7 @@
   // Test that |manifest.name| takes priority over |manifest.short_name|, and
   // that icons provided by the manifest replace icons in |web_app_info|.
   manifest.name = base::NullableString16(base::UTF8ToUTF16(kAppTitle), false);
+  manifest.display = blink::mojom::DisplayMode::kMinimalUi;
 
   blink::Manifest::ImageResource icon;
   icon.src = kAppIcon2;
@@ -75,6 +78,7 @@
   UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                ForInstallableSite::kNo);
   EXPECT_EQ(base::UTF8ToUTF16(kAppTitle), web_app_info.title);
+  EXPECT_EQ(blink::mojom::DisplayMode::kMinimalUi, web_app_info.display_mode);
 
   EXPECT_EQ(2u, web_app_info.icons.size());
   EXPECT_EQ(kAppIcon2, web_app_info.icons[0].url);
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
index 8791e522..b80b161 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
@@ -150,7 +150,7 @@
   return base::nullopt;
 }
 
-blink::mojom::DisplayMode BookmarkAppRegistrar::GetAppDisplayMode(
+blink::mojom::DisplayMode BookmarkAppRegistrar::GetAppUserDisplayMode(
     const web_app::AppId& app_id) const {
   const Extension* extension = GetExtension(app_id);
   if (!extension)
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registrar.h b/chrome/browser/web_applications/extensions/bookmark_app_registrar.h
index a1fa1bb..8bf0a2f 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_registrar.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_registrar.h
@@ -38,7 +38,7 @@
       const web_app::AppId& app_id) const override;
   const GURL& GetAppLaunchURL(const web_app::AppId& app_id) const override;
   base::Optional<GURL> GetAppScope(const web_app::AppId& app_id) const override;
-  blink::mojom::DisplayMode GetAppDisplayMode(
+  blink::mojom::DisplayMode GetAppUserDisplayMode(
       const web_app::AppId& app_id) const override;
   std::vector<web_app::AppId> GetAppIds() const override;
 
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc
index 0be436a..4656feeb 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc
@@ -36,7 +36,7 @@
   return extension;
 }
 
-void BookmarkAppRegistryController::SetAppDisplayMode(
+void BookmarkAppRegistryController::SetAppUserDisplayMode(
     const web_app::AppId& app_id,
     blink::mojom::DisplayMode display_mode) {
   const Extension* extension = GetExtension(app_id);
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h
index 2021d7f..969a30ee 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h
@@ -20,8 +20,8 @@
 
   // AppRegistryController:
   void Init(base::OnceClosure callback) override;
-  void SetAppDisplayMode(const web_app::AppId& app_id,
-                         blink::mojom::DisplayMode display_mode) override;
+  void SetAppUserDisplayMode(const web_app::AppId& app_id,
+                             blink::mojom::DisplayMode display_mode) override;
   void SetAppIsLocallyInstalledForTesting(const web_app::AppId& app_id,
                                           bool is_locally_installed) override;
   web_app::WebAppSyncBridge* AsWebAppSyncBridge() override;
diff --git a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
index 0f6e076..2b06096 100644
--- a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
+++ b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
@@ -530,7 +530,7 @@
                                            /*is_installable=*/true);
 
     web_app::InstallManager::InstallParams params;
-    params.display_mode = blink::mojom::DisplayMode::kBrowser;
+    params.user_display_mode = blink::mojom::DisplayMode::kBrowser;
 
     const Extension* extension =
         InstallWebAppWithParams(WebappInstallSource::INTERNAL_DEFAULT, params);
@@ -543,7 +543,7 @@
                                            /*is_installable=*/false);
 
     web_app::InstallManager::InstallParams params;
-    params.display_mode = blink::mojom::DisplayMode::kStandalone;
+    params.user_display_mode = blink::mojom::DisplayMode::kStandalone;
 
     const Extension* extension =
         InstallWebAppWithParams(WebappInstallSource::INTERNAL_DEFAULT, params);
diff --git a/chrome/browser/web_applications/external_web_app_manager.cc b/chrome/browser/web_applications/external_web_app_manager.cc
index de83d893..19e71863 100644
--- a/chrome/browser/web_applications/external_web_app_manager.cc
+++ b/chrome/browser/web_applications/external_web_app_manager.cc
@@ -172,13 +172,12 @@
       continue;
     }
     std::string launch_container_str = value->GetString();
-    auto display_mode = blink::mojom::DisplayMode::kBrowser;
+    auto user_display_mode = blink::mojom::DisplayMode::kBrowser;
     if (launch_container_str == kLaunchContainerTab) {
-      display_mode = blink::mojom::DisplayMode::kBrowser;
+      user_display_mode = blink::mojom::DisplayMode::kBrowser;
     } else if (launch_container_str == kLaunchContainerWindow) {
-      display_mode = blink::mojom::DisplayMode::kStandalone;
+      user_display_mode = blink::mojom::DisplayMode::kStandalone;
     } else {
-      // TODO(crbug.com/1009909): Support Minimal UI.
       LOG(ERROR) << file.value() << " had an invalid " << kLaunchContainer;
       continue;
     }
@@ -209,7 +208,7 @@
     }
 
     ExternalInstallOptions install_options(
-        std::move(app_url), display_mode,
+        std::move(app_url), user_display_mode,
         ExternalInstallSource::kExternalDefault);
     install_options.add_to_applications_menu = create_shortcuts;
     install_options.add_to_desktop = create_shortcuts;
diff --git a/chrome/browser/web_applications/pending_app_install_task.cc b/chrome/browser/web_applications/pending_app_install_task.cc
index 1e30febe..d119a2f6 100644
--- a/chrome/browser/web_applications/pending_app_install_task.cc
+++ b/chrome/browser/web_applications/pending_app_install_task.cc
@@ -178,7 +178,7 @@
   web_app_info.title = base::UTF8ToUTF16(install_options_.url.spec());
   web_app_info.app_url = install_options_.url;
 
-  switch (install_options_.display_mode) {
+  switch (install_options_.user_display_mode) {
     case blink::mojom::DisplayMode::kUndefined:
     case blink::mojom::DisplayMode::kBrowser:
       web_app_info.open_as_window = false;
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto
index e07bbf3..deb8e99 100644
--- a/chrome/browser/web_applications/proto/web_app.proto
+++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -40,15 +40,26 @@
   // |name| and |theme_color|. A random last update wins.
   required sync_pb.WebAppSpecifics sync_data = 1;
 
+  // This enum should be synced with
+  // third_party/blink/public/mojom/manifest/display_mode.mojom
+  enum DisplayMode {
+    // UNDEFINED is never serialized.
+    BROWSER = 1;
+    MINIMAL_UI = 2;
+    STANDALONE = 3;
+    FULLSCREEN = 4;
+  }
+
   // Local data. May vary across devices. Not to be synced.
   //
   required string name = 2;
   optional uint32 theme_color = 3;
   optional string description = 4;
-  optional string scope = 5;
-  required SourcesProto sources = 6;
-  required bool is_locally_installed = 7;
-  optional bool is_in_sync_install = 8;
+  optional DisplayMode display_mode = 5;
+  optional string scope = 6;
+  required SourcesProto sources = 7;
+  required bool is_locally_installed = 8;
+  optional bool is_in_sync_install = 9;
   // A list of icon infos.
-  repeated WebAppIconInfoProto icons = 9;
+  repeated WebAppIconInfoProto icons = 10;
 }
diff --git a/chrome/browser/web_applications/test/test_app_registrar.cc b/chrome/browser/web_applications/test/test_app_registrar.cc
index b6625a0d..ddb001b 100644
--- a/chrome/browser/web_applications/test/test_app_registrar.cc
+++ b/chrome/browser/web_applications/test/test_app_registrar.cc
@@ -130,7 +130,7 @@
   return base::make_optional(result->second.install_url);
 }
 
-blink::mojom::DisplayMode TestAppRegistrar::GetAppDisplayMode(
+blink::mojom::DisplayMode TestAppRegistrar::GetAppUserDisplayMode(
     const AppId& app_id) const {
   NOTIMPLEMENTED();
   return blink::mojom::DisplayMode::kBrowser;
diff --git a/chrome/browser/web_applications/test/test_app_registrar.h b/chrome/browser/web_applications/test/test_app_registrar.h
index b0b1574..5d1aea90 100644
--- a/chrome/browser/web_applications/test/test_app_registrar.h
+++ b/chrome/browser/web_applications/test/test_app_registrar.h
@@ -57,7 +57,7 @@
   base::Optional<SkColor> GetAppThemeColor(const AppId& app_id) const override;
   const GURL& GetAppLaunchURL(const AppId& app_id) const override;
   base::Optional<GURL> GetAppScope(const AppId& app_id) const override;
-  blink::mojom::DisplayMode GetAppDisplayMode(
+  blink::mojom::DisplayMode GetAppUserDisplayMode(
       const web_app::AppId& app_id) const override;
   std::vector<AppId> GetAppIds() const override;
 
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index dc23d8d..cbea1c0a 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -15,7 +15,9 @@
 namespace web_app {
 
 WebApp::WebApp(const AppId& app_id)
-    : app_id_(app_id), display_mode_(blink::mojom::DisplayMode::kUndefined) {}
+    : app_id_(app_id),
+      display_mode_(blink::mojom::DisplayMode::kUndefined),
+      user_display_mode_(blink::mojom::DisplayMode::kUndefined) {}
 
 WebApp::~WebApp() = default;
 
@@ -66,6 +68,22 @@
   display_mode_ = display_mode;
 }
 
+void WebApp::SetUserDisplayMode(blink::mojom::DisplayMode user_display_mode) {
+  switch (user_display_mode) {
+    case blink::mojom::DisplayMode::kBrowser:
+      user_display_mode_ = blink::mojom::DisplayMode::kBrowser;
+      break;
+    case blink::mojom::DisplayMode::kUndefined:
+    case blink::mojom::DisplayMode::kMinimalUi:
+    case blink::mojom::DisplayMode::kFullscreen:
+      NOTREACHED();
+      FALLTHROUGH;
+    case blink::mojom::DisplayMode::kStandalone:
+      user_display_mode_ = blink::mojom::DisplayMode::kStandalone;
+      break;
+  }
+}
+
 void WebApp::SetIsLocallyInstalled(bool is_locally_installed) {
   is_locally_installed_ = is_locally_installed;
 }
@@ -101,6 +119,8 @@
           : "none";
   const std::string display_mode =
       blink::DisplayModeToString(app.display_mode_);
+  const std::string user_display_mode =
+      blink::DisplayModeToString(app.user_display_mode_);
   const bool is_locally_installed = app.is_locally_installed_;
   const bool is_in_sync_install = app.is_in_sync_install_;
 
@@ -110,6 +130,7 @@
              << "  scope: " << app.scope_ << std::endl
              << "  theme_color: " << theme_color << std::endl
              << "  display_mode: " << display_mode << std::endl
+             << "  user_display_mode: " << user_display_mode << std::endl
              << "  sources: " << app.sources_.to_string() << std::endl
              << "  is_locally_installed: " << is_locally_installed << std::endl
              << "  is_in_sync_install: " << is_in_sync_install << std::endl
@@ -133,12 +154,14 @@
 bool operator==(const WebApp& app1, const WebApp& app2) {
   return std::tie(app1.app_id_, app1.sources_, app1.name_, app1.launch_url_,
                   app1.description_, app1.scope_, app1.theme_color_,
-                  app1.icons_, app1.display_mode_, app1.is_locally_installed_,
-                  app1.is_in_sync_install_, app1.sync_data_) ==
+                  app1.icons_, app1.display_mode_, app1.user_display_mode_,
+                  app1.is_locally_installed_, app1.is_in_sync_install_,
+                  app1.sync_data_) ==
          std::tie(app2.app_id_, app2.sources_, app2.name_, app2.launch_url_,
                   app2.description_, app2.scope_, app2.theme_color_,
-                  app2.icons_, app2.display_mode_, app2.is_locally_installed_,
-                  app2.is_in_sync_install_, app2.sync_data_);
+                  app2.icons_, app2.display_mode_, app2.user_display_mode_,
+                  app2.is_locally_installed_, app2.is_in_sync_install_,
+                  app2.sync_data_);
 }
 
 bool operator!=(const WebApp& app1, const WebApp& app2) {
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index d027472..202493e 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -40,6 +40,11 @@
   const GURL& scope() const { return scope_; }
   const base::Optional<SkColor>& theme_color() const { return theme_color_; }
   blink::mojom::DisplayMode display_mode() const { return display_mode_; }
+
+  blink::mojom::DisplayMode user_display_mode() const {
+    return user_display_mode_;
+  }
+
   // Locally installed apps have shortcuts installed on various UI surfaces.
   // If app isn't locally installed, it is excluded from UIs and only listed as
   // a part of user's app library.
@@ -88,6 +93,7 @@
   void SetScope(const GURL& scope);
   void SetThemeColor(base::Optional<SkColor> theme_color);
   void SetDisplayMode(blink::mojom::DisplayMode display_mode);
+  void SetUserDisplayMode(blink::mojom::DisplayMode user_display_mode);
   void SetIsLocallyInstalled(bool is_locally_installed);
   void SetIsInSyncInstall(bool is_in_sync_install);
   void SetIcons(Icons icons);
@@ -113,6 +119,7 @@
   GURL scope_;
   base::Optional<SkColor> theme_color_;
   blink::mojom::DisplayMode display_mode_;
+  blink::mojom::DisplayMode user_display_mode_;
   bool is_locally_installed_ = true;
   bool is_in_sync_install_ = false;
   Icons icons_;
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc
index 86ab9734..e38a6b5 100644
--- a/chrome/browser/web_applications/web_app_database.cc
+++ b/chrome/browser/web_applications/web_app_database.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
-#include "chrome/browser/web_applications/proto/web_app.pb.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_database_factory.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
@@ -94,8 +93,10 @@
 
   local_data->set_name(web_app.name());
 
-  sync_data->set_display_mode(
-      ToWebAppSpecificsDisplayMode(web_app.display_mode()));
+  local_data->set_display_mode(
+      ToWebAppProtoDisplayMode(web_app.display_mode()));
+  sync_data->set_user_display_mode(
+      ToWebAppSpecificsUserDisplayMode(web_app.user_display_mode()));
 
   DCHECK(web_app.sources_.any());
   local_data->mutable_sources()->set_system(web_app.sources_[Source::kSystem]);
@@ -178,11 +179,18 @@
   }
   web_app->SetName(local_data.name());
 
-  if (!sync_data.has_display_mode()) {
+  if (!local_data.has_display_mode()) {
     DLOG(ERROR) << "WebApp proto parse error: no display_mode field";
     return nullptr;
   }
-  web_app->SetDisplayMode(ToMojomDisplayMode(sync_data.display_mode()));
+  web_app->SetDisplayMode(ToMojomDisplayMode(local_data.display_mode()));
+
+  if (!sync_data.has_user_display_mode()) {
+    DLOG(ERROR) << "WebApp proto parse error: no user_display_mode field";
+    return nullptr;
+  }
+  web_app->SetUserDisplayMode(
+      ToMojomDisplayMode(sync_data.user_display_mode()));
 
   if (!local_data.has_is_locally_installed()) {
     DLOG(ERROR) << "WebApp proto parse error: no is_locally_installed field";
@@ -327,30 +335,57 @@
 }
 
 blink::mojom::DisplayMode ToMojomDisplayMode(
-    ::sync_pb::WebAppSpecifics::DisplayMode display_mode) {
+    WebAppProto::DisplayMode display_mode) {
   switch (display_mode) {
+    case WebAppProto::BROWSER:
+      return blink::mojom::DisplayMode::kBrowser;
+    case WebAppProto::MINIMAL_UI:
+      return blink::mojom::DisplayMode::kMinimalUi;
+    case WebAppProto::STANDALONE:
+      return blink::mojom::DisplayMode::kStandalone;
+    case WebAppProto::FULLSCREEN:
+      return blink::mojom::DisplayMode::kFullscreen;
+  }
+}
+
+blink::mojom::DisplayMode ToMojomDisplayMode(
+    ::sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode) {
+  switch (user_display_mode) {
     case ::sync_pb::WebAppSpecifics::BROWSER:
       return blink::mojom::DisplayMode::kBrowser;
-    case ::sync_pb::WebAppSpecifics::MINIMAL_UI:
-      return blink::mojom::DisplayMode::kMinimalUi;
     case ::sync_pb::WebAppSpecifics::STANDALONE:
       return blink::mojom::DisplayMode::kStandalone;
   }
 }
 
-::sync_pb::WebAppSpecifics::DisplayMode ToWebAppSpecificsDisplayMode(
+WebAppProto::DisplayMode ToWebAppProtoDisplayMode(
     blink::mojom::DisplayMode display_mode) {
   switch (display_mode) {
     case blink::mojom::DisplayMode::kBrowser:
-      return ::sync_pb::WebAppSpecifics::BROWSER;
+      return WebAppProto::BROWSER;
     case blink::mojom::DisplayMode::kMinimalUi:
-      return ::sync_pb::WebAppSpecifics::MINIMAL_UI;
+      return WebAppProto::MINIMAL_UI;
     case blink::mojom::DisplayMode::kUndefined:
       NOTREACHED();
       FALLTHROUGH;
-    case blink::mojom::DisplayMode::kFullscreen:
     case blink::mojom::DisplayMode::kStandalone:
-      // We do not persist kFullscreen - see crbug.com/850465.
+      return WebAppProto::STANDALONE;
+    case blink::mojom::DisplayMode::kFullscreen:
+      return WebAppProto::FULLSCREEN;
+  }
+}
+
+::sync_pb::WebAppSpecifics::UserDisplayMode ToWebAppSpecificsUserDisplayMode(
+    blink::mojom::DisplayMode user_display_mode) {
+  switch (user_display_mode) {
+    case blink::mojom::DisplayMode::kBrowser:
+      return ::sync_pb::WebAppSpecifics::BROWSER;
+    case blink::mojom::DisplayMode::kUndefined:
+    case blink::mojom::DisplayMode::kMinimalUi:
+    case blink::mojom::DisplayMode::kFullscreen:
+      NOTREACHED();
+      FALLTHROUGH;
+    case blink::mojom::DisplayMode::kStandalone:
       return ::sync_pb::WebAppSpecifics::STANDALONE;
   }
 }
diff --git a/chrome/browser/web_applications/web_app_database.h b/chrome/browser/web_applications/web_app_database.h
index ce62631..ef5ea55 100644
--- a/chrome/browser/web_applications/web_app_database.h
+++ b/chrome/browser/web_applications/web_app_database.h
@@ -13,6 +13,7 @@
 #include "base/optional.h"
 #include "base/sequence_checker.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/proto/web_app.pb.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/protocol/web_app_specifics.pb.h"
@@ -93,11 +94,17 @@
 };
 
 blink::mojom::DisplayMode ToMojomDisplayMode(
-    ::sync_pb::WebAppSpecifics::DisplayMode display_mode);
+    WebAppProto::DisplayMode display_mode);
 
-::sync_pb::WebAppSpecifics::DisplayMode ToWebAppSpecificsDisplayMode(
+blink::mojom::DisplayMode ToMojomDisplayMode(
+    ::sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode);
+
+WebAppProto::DisplayMode ToWebAppProtoDisplayMode(
     blink::mojom::DisplayMode display_mode);
 
+::sync_pb::WebAppSpecifics::UserDisplayMode ToWebAppSpecificsUserDisplayMode(
+    blink::mojom::DisplayMode user_display_mode);
+
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_H_
diff --git a/chrome/browser/web_applications/web_app_database_unittest.cc b/chrome/browser/web_applications/web_app_database_unittest.cc
index bc672c4..3b3f9f6 100644
--- a/chrome/browser/web_applications/web_app_database_unittest.cc
+++ b/chrome/browser/web_applications/web_app_database_unittest.cc
@@ -72,8 +72,16 @@
     app->SetThemeColor(theme_color);
     app->SetIsLocallyInstalled(!(suffix & 2));
     app->SetIsInSyncInstall(!(suffix & 4));
-    app->SetDisplayMode((suffix & 1) ? blink::mojom::DisplayMode::kBrowser
-                                     : blink::mojom::DisplayMode::kStandalone);
+    app->SetUserDisplayMode((suffix & 1)
+                                ? blink::mojom::DisplayMode::kBrowser
+                                : blink::mojom::DisplayMode::kStandalone);
+
+    const blink::mojom::DisplayMode display_modes[4] = {
+        blink::mojom::DisplayMode::kBrowser,
+        blink::mojom::DisplayMode::kMinimalUi,
+        blink::mojom::DisplayMode::kStandalone,
+        blink::mojom::DisplayMode::kFullscreen};
+    app->SetDisplayMode(display_modes[(suffix >> 4) & 3]);
 
     const std::string icon_url =
         base_url + "/icon" + base::NumberToString(suffix);
@@ -258,6 +266,7 @@
   app->SetLaunchUrl(launch_url);
   app->SetName(name);
   app->SetDisplayMode(display_mode);
+  app->SetUserDisplayMode(display_mode);
   app->SetIsLocallyInstalled(false);
 
   EXPECT_FALSE(app->HasAnySources());
@@ -286,6 +295,7 @@
   EXPECT_EQ(launch_url, app_copy->launch_url());
   EXPECT_EQ(name, app_copy->name());
   EXPECT_EQ(display_mode, app_copy->display_mode());
+  EXPECT_EQ(display_mode, app_copy->user_display_mode());
   EXPECT_FALSE(app_copy->is_locally_installed());
 
   for (int i = Source::kMinValue; i < Source::kMaxValue; ++i) {
diff --git a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
index f8e875ae..8f4c4fe 100644
--- a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
@@ -87,6 +87,7 @@
     auto web_app = std::make_unique<WebApp>(app_id);
     web_app->AddSource(Source::kSync);
     web_app->SetDisplayMode(blink::mojom::DisplayMode::kStandalone);
+    web_app->SetUserDisplayMode(blink::mojom::DisplayMode::kStandalone);
     web_app->SetName("Name");
     web_app->SetLaunchUrl(app_url);
 
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 77b3de30..5153955a 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -127,9 +127,10 @@
     web_app->SetThemeColor(
         SkColorSetA(*web_app_info.theme_color, SK_AlphaOPAQUE));
   }
-  web_app->SetDisplayMode(web_app_info.open_as_window
-                              ? blink::mojom::DisplayMode::kStandalone
-                              : blink::mojom::DisplayMode::kBrowser);
+  web_app->SetDisplayMode(web_app_info.display_mode);
+  web_app->SetUserDisplayMode(web_app_info.open_as_window
+                                  ? blink::mojom::DisplayMode::kStandalone
+                                  : blink::mojom::DisplayMode::kBrowser);
   web_app->SetIsLocallyInstalled(options.locally_installed);
 
   SetWebAppIcons(web_app_info.icons, web_app.get());
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc
index b9e15987..e1513929 100644
--- a/chrome/browser/web_applications/web_app_install_task.cc
+++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -505,10 +505,10 @@
 
   InstallFinalizer::FinalizeOptions finalize_options;
   finalize_options.install_source = install_source_;
-  if (install_params_ &&
-      install_params_->display_mode != blink::mojom::DisplayMode::kUndefined) {
-    web_app_info_copy.open_as_window =
-        install_params_->display_mode != blink::mojom::DisplayMode::kBrowser;
+  if (install_params_ && install_params_->user_display_mode !=
+                             blink::mojom::DisplayMode::kUndefined) {
+    web_app_info_copy.open_as_window = install_params_->user_display_mode !=
+                                       blink::mojom::DisplayMode::kBrowser;
   }
 
   install_finalizer_->FinalizeInstall(
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index 99975d4d..f31604b10 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -504,6 +504,7 @@
   const GURL manifest_scope = GURL("https://example.com/scope");
   const base::Optional<SkColor> manifest_theme_color = 0xAABBCCDD;
   const base::Optional<SkColor> expected_theme_color = 0xFFBBCCDD;  // Opaque.
+  const auto display_mode = blink::mojom::DisplayMode::kMinimalUi;
 
   {
     auto manifest = std::make_unique<blink::Manifest>();
@@ -512,6 +513,7 @@
     manifest->start_url = manifest_start_url;
     manifest->scope = manifest_scope;
     manifest->theme_color = manifest_theme_color;
+    manifest->display = display_mode;
 
     data_retriever_->SetManifest(std::move(manifest), /*is_installable=*/true);
   }
@@ -544,6 +546,7 @@
   EXPECT_EQ(renderer_description, web_app->description());
   EXPECT_EQ(manifest_scope, web_app->scope());
   EXPECT_EQ(expected_theme_color, web_app->theme_color());
+  EXPECT_EQ(display_mode, web_app->display_mode());
 }
 
 TEST_F(WebAppInstallTaskTest, GetIcons) {
@@ -1113,42 +1116,42 @@
                          /*open_as_window*/ false);
 
     InstallManager::InstallParams params;
-    params.display_mode = blink::mojom::DisplayMode::kUndefined;
+    params.user_display_mode = blink::mojom::DisplayMode::kUndefined;
     auto app_id = InstallWebAppWithParams(params);
 
     EXPECT_EQ(blink::mojom::DisplayMode::kBrowser,
-              registrar().GetAppById(app_id)->display_mode());
+              registrar().GetAppById(app_id)->user_display_mode());
   }
   {
     CreateDataToRetrieve(GURL("https://example.org/"), /*open_as_window*/ true);
 
     InstallManager::InstallParams params;
-    params.display_mode = blink::mojom::DisplayMode::kUndefined;
+    params.user_display_mode = blink::mojom::DisplayMode::kUndefined;
     auto app_id = InstallWebAppWithParams(params);
 
     EXPECT_EQ(blink::mojom::DisplayMode::kStandalone,
-              registrar().GetAppById(app_id)->display_mode());
+              registrar().GetAppById(app_id)->user_display_mode());
   }
   {
     CreateDataToRetrieve(GURL("https://example.au/"), /*open_as_window*/ true);
 
     InstallManager::InstallParams params;
-    params.display_mode = blink::mojom::DisplayMode::kBrowser;
+    params.user_display_mode = blink::mojom::DisplayMode::kBrowser;
     auto app_id = InstallWebAppWithParams(params);
 
     EXPECT_EQ(blink::mojom::DisplayMode::kBrowser,
-              registrar().GetAppById(app_id)->display_mode());
+              registrar().GetAppById(app_id)->user_display_mode());
   }
   {
     CreateDataToRetrieve(GURL("https://example.app/"),
                          /*open_as_window*/ false);
 
     InstallManager::InstallParams params;
-    params.display_mode = blink::mojom::DisplayMode::kStandalone;
+    params.user_display_mode = blink::mojom::DisplayMode::kStandalone;
     auto app_id = InstallWebAppWithParams(params);
 
     EXPECT_EQ(blink::mojom::DisplayMode::kStandalone,
-              registrar().GetAppById(app_id)->display_mode());
+              registrar().GetAppById(app_id)->user_display_mode());
   }
 }
 
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index 353190f..5e71e10 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -117,10 +117,10 @@
   return web_app ? base::Optional<GURL>(web_app->scope()) : base::nullopt;
 }
 
-blink::mojom::DisplayMode WebAppRegistrar::GetAppDisplayMode(
+blink::mojom::DisplayMode WebAppRegistrar::GetAppUserDisplayMode(
     const web_app::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
-  return web_app ? web_app->display_mode()
+  return web_app ? web_app->user_display_mode()
                  : blink::mojom::DisplayMode::kUndefined;
 }
 
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index bf3f099..01f42e5d 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -43,7 +43,7 @@
   base::Optional<SkColor> GetAppThemeColor(const AppId& app_id) const override;
   const GURL& GetAppLaunchURL(const AppId& app_id) const override;
   base::Optional<GURL> GetAppScope(const AppId& app_id) const override;
-  blink::mojom::DisplayMode GetAppDisplayMode(
+  blink::mojom::DisplayMode GetAppUserDisplayMode(
       const web_app::AppId& app_id) const override;
   std::vector<AppId> GetAppIds() const override;
 
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc
index e5e98e5c..e8452d11 100644
--- a/chrome/browser/web_applications/web_app_registrar_unittest.cc
+++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -41,6 +41,7 @@
     web_app->AddSource(Source::kSync);
     web_app->SetLaunchUrl(GURL(url));
     web_app->SetDisplayMode(blink::mojom::DisplayMode::kBrowser);
+    web_app->SetUserDisplayMode(blink::mojom::DisplayMode::kBrowser);
 
     registry.emplace(app_id, std::move(web_app));
   }
@@ -132,6 +133,7 @@
 
     web_app->AddSource(Source::kSync);
     web_app->SetDisplayMode(blink::mojom::DisplayMode::kStandalone);
+    web_app->SetUserDisplayMode(blink::mojom::DisplayMode::kStandalone);
     web_app->SetName("Name");
     web_app->SetLaunchUrl(launch_url);
     return web_app;
@@ -173,6 +175,7 @@
 
   web_app->AddSource(Source::kSync);
   web_app->SetDisplayMode(blink::mojom::DisplayMode::kStandalone);
+  web_app->SetUserDisplayMode(blink::mojom::DisplayMode::kStandalone);
   web_app->SetName(name);
   web_app->SetDescription(description);
   web_app->SetLaunchUrl(launch_url);
@@ -181,6 +184,7 @@
 
   web_app2->AddSource(Source::kDefault);
   web_app2->SetDisplayMode(blink::mojom::DisplayMode::kBrowser);
+  web_app2->SetUserDisplayMode(blink::mojom::DisplayMode::kBrowser);
   web_app2->SetLaunchUrl(launch_url2);
 
   EXPECT_EQ(nullptr, registrar().GetAppById(app_id));
@@ -307,7 +311,8 @@
   const std::string name = "Name";
   const std::string description = "Description";
   const base::Optional<SkColor> theme_color = 0xAABBCCDD;
-  const auto display_mode = blink::mojom::DisplayMode::kStandalone;
+  const auto display_mode = blink::mojom::DisplayMode::kMinimalUi;
+  const auto user_display_mode = blink::mojom::DisplayMode::kStandalone;
 
   EXPECT_EQ(std::string(), registrar().GetAppShortName(app_id));
   EXPECT_EQ(GURL(), registrar().GetAppLaunchURL(app_id));
@@ -321,6 +326,7 @@
   web_app->SetThemeColor(theme_color);
   web_app->SetLaunchUrl(launch_url);
   web_app->SetDisplayMode(display_mode);
+  web_app->SetUserDisplayMode(user_display_mode);
   web_app->SetIsLocallyInstalled(/*is_locally_installed*/ false);
 
   RegisterApp(std::move(web_app));
@@ -330,7 +336,7 @@
   EXPECT_EQ(theme_color, registrar().GetAppThemeColor(app_id));
   EXPECT_EQ(launch_url, registrar().GetAppLaunchURL(app_id));
   EXPECT_EQ(blink::mojom::DisplayMode::kStandalone,
-            registrar().GetAppDisplayMode(app_id));
+            registrar().GetAppUserDisplayMode(app_id));
 
   {
     EXPECT_FALSE(registrar().IsLocallyInstalled(app_id));
@@ -342,15 +348,17 @@
 
   {
     EXPECT_EQ(blink::mojom::DisplayMode::kUndefined,
-              registrar().GetAppDisplayMode("unknown"));
+              registrar().GetAppUserDisplayMode("unknown"));
 
-    web_app_ptr->SetDisplayMode(blink::mojom::DisplayMode::kBrowser);
+    web_app_ptr->SetUserDisplayMode(blink::mojom::DisplayMode::kBrowser);
     EXPECT_EQ(blink::mojom::DisplayMode::kBrowser,
-              registrar().GetAppDisplayMode(app_id));
+              registrar().GetAppUserDisplayMode(app_id));
 
-    sync_bridge().SetAppDisplayMode(app_id,
-                                    blink::mojom::DisplayMode::kStandalone);
+    sync_bridge().SetAppUserDisplayMode(app_id,
+                                        blink::mojom::DisplayMode::kStandalone);
     EXPECT_EQ(blink::mojom::DisplayMode::kStandalone,
+              web_app_ptr->user_display_mode());
+    EXPECT_EQ(blink::mojom::DisplayMode::kMinimalUi,
               web_app_ptr->display_mode());
   }
 }
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc
index adabeb6e..c7fdac8 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -44,7 +44,8 @@
   sync_pb::WebAppSpecifics* sync_data =
       entity_data->specifics.mutable_web_app();
   sync_data->set_launch_url(app.launch_url().spec());
-  sync_data->set_display_mode(ToWebAppSpecificsDisplayMode(app.display_mode()));
+  sync_data->set_user_display_mode(
+      ToWebAppSpecificsUserDisplayMode(app.user_display_mode()));
   sync_data->set_name(app.sync_data().name);
   if (app.sync_data().theme_color.has_value())
     sync_data->set_theme_color(app.sync_data().theme_color.value());
@@ -75,8 +76,8 @@
     return;
   }
 
-  // Always override display mode with a synced value.
-  app->SetDisplayMode(ToMojomDisplayMode(sync_data.display_mode()));
+  // Always override user_display mode with a synced value.
+  app->SetUserDisplayMode(ToMojomDisplayMode(sync_data.user_display_mode()));
 
   WebApp::SyncData parsed_sync_data;
   parsed_sync_data.name = sync_data.name();
@@ -171,13 +172,13 @@
                                          std::move(callback)));
 }
 
-void WebAppSyncBridge::SetAppDisplayMode(
+void WebAppSyncBridge::SetAppUserDisplayMode(
     const AppId& app_id,
-    blink::mojom::DisplayMode display_mode) {
+    blink::mojom::DisplayMode user_display_mode) {
   ScopedRegistryUpdate update(this);
   WebApp* web_app = update->UpdateApp(app_id);
   if (web_app)
-    web_app->SetDisplayMode(display_mode);
+    web_app->SetUserDisplayMode(user_display_mode);
 }
 
 void WebAppSyncBridge::SetAppIsLocallyInstalledForTesting(
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.h b/chrome/browser/web_applications/web_app_sync_bridge.h
index 9c549b4..e0ae897 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.h
+++ b/chrome/browser/web_applications/web_app_sync_bridge.h
@@ -61,8 +61,9 @@
 
   // AppRegistryController:
   void Init(base::OnceClosure callback) override;
-  void SetAppDisplayMode(const AppId& app_id,
-                         blink::mojom::DisplayMode display_mode) override;
+  void SetAppUserDisplayMode(
+      const AppId& app_id,
+      blink::mojom::DisplayMode user_display_mode) override;
   void SetAppIsLocallyInstalledForTesting(const AppId& app_id,
                                           bool is_locally_installed) override;
   WebAppSyncBridge* AsWebAppSyncBridge() override;