From dc4149ec01cf430b7c56d35ed49327f2d6c2f1a5 Mon Sep 17 00:00:00 2001
From: Tim Sullivan <tsullivan@users.noreply.github.com>
Date: Fri, 6 Dec 2024 10:09:23 -0700
Subject: [PATCH] Preparation for High Contrast Mode, Kibana-Management domains
 (#202607)

## Summary

**Reviewers: Please test the code paths affected by this PR. See the
"Risks" section below.**

Part of work for enabling "high contrast mode" in Kibana. See
https://github.com/elastic/kibana/issues/176219

**Background:**
Kibana will soon have a user profile setting to allow users to enable
"high contrast mode." This setting will activate a flag with
`<EuiProvider>` that causes EUI components to render with higher
contrast visual elements. Consumer plugins and packages need to be
updated selected places where `<EuiProvider>` is wrapped, to pass the
`UserProfileService` service dependency from the CoreStart contract.

### Checklist

Check the PR satisfies following conditions.

Reviewers should verify this PR satisfies this list as well.

- [X] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [X] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

### Risks

Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] [medium/high] The implementor of this change did not manually test
the affected code paths and relied on type-checking and functional tests
to drive the changes. Code owners for this PR need to manually test the
affected code paths.
- [ ] [medium] The `UserProfileService` dependency comes from the
CoreStart contract. If acquiring the service causes synchronous code to
become asynchronous, check for race conditions or errors in rendering
React components. Code owners for this PR need to manually test the
affected code paths.
---
 .../kbn-management/settings/application/index.tsx     |  2 ++
 .../settings/application/mocks/context.tsx            |  3 +++
 .../kbn-management/settings/application/services.tsx  |  3 ++-
 .../kbn-management/settings/application/tsconfig.json |  1 +
 .../components/field_input/mocks/context.mock.tsx     |  3 +++
 .../settings/components/field_input/tsconfig.json     |  1 +
 .../settings/components/field_row/mocks/context.tsx   |  3 +++
 .../settings/components/field_row/tsconfig.json       |  1 +
 .../settings/components/form/mocks/context.tsx        |  3 +++
 .../settings/components/form/reload_page_toast.tsx    | 11 +++++++++--
 .../settings/components/form/services.tsx             |  4 ++--
 .../settings/components/form/tsconfig.json            |  2 ++
 .../kbn-management/settings/components/form/types.ts  |  2 ++
 .../console/public/types/plugin_dependencies.ts       |  8 +++++++-
 src/plugins/dev_tools/public/plugin.ts                |  4 ++--
 src/plugins/dev_tools/public/types.ts                 |  8 +++++++-
 src/plugins/guided_onboarding/public/plugin.tsx       |  2 +-
 .../components/management_app/management_app.tsx      |  2 +-
 .../cross_cluster_replication/public/app/index.tsx    |  2 +-
 .../index_management/public/application/index.tsx     |  5 ++++-
 x-pack/plugins/index_management/public/types.ts       |  2 ++
 .../ingest_pipelines/public/application/index.tsx     |  2 +-
 x-pack/plugins/painless_lab/public/plugin.tsx         | 11 +----------
 x-pack/plugins/painless_lab/public/types.ts           |  8 +++++++-
 .../remote_clusters/public/application/index.d.ts     |  2 +-
 x-pack/plugins/searchprofiler/public/plugin.ts        |  3 +--
 x-pack/plugins/searchprofiler/public/types.ts         |  8 +++++++-
 .../client_integration/helpers/app_context.mock.tsx   |  1 +
 x-pack/plugins/watcher/public/application/app.tsx     |  2 ++
 29 files changed, 80 insertions(+), 29 deletions(-)

diff --git a/packages/kbn-management/settings/application/index.tsx b/packages/kbn-management/settings/application/index.tsx
index aac5bccdafb4d..35366a1132aed 100644
--- a/packages/kbn-management/settings/application/index.tsx
+++ b/packages/kbn-management/settings/application/index.tsx
@@ -27,6 +27,7 @@ export const KibanaSettingsApplication = ({
   i18n,
   notifications,
   settings,
+  userProfile,
   theme,
   history,
   sectionRegistry,
@@ -36,6 +37,7 @@ export const KibanaSettingsApplication = ({
   <SettingsApplicationKibanaProvider
     {...{
       settings,
+      userProfile,
       theme,
       i18n,
       notifications,
diff --git a/packages/kbn-management/settings/application/mocks/context.tsx b/packages/kbn-management/settings/application/mocks/context.tsx
index 644506f47323f..46490908e03c3 100644
--- a/packages/kbn-management/settings/application/mocks/context.tsx
+++ b/packages/kbn-management/settings/application/mocks/context.tsx
@@ -11,6 +11,7 @@ import React, { ReactChild } from 'react';
 import { I18nProvider } from '@kbn/i18n-react';
 
 import { KibanaRootContextProvider } from '@kbn/react-kibana-context-root';
+import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
 import { themeServiceMock } from '@kbn/core-theme-browser-mocks';
 import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks';
 import { I18nStart } from '@kbn/core-i18n-browser';
@@ -31,10 +32,12 @@ const createRootMock = () => {
     Context: ({ children }) => <I18nProvider>{children}</I18nProvider>,
   };
   const theme = themeServiceMock.createStartContract();
+  const userProfile = userProfileServiceMock.createStart();
   return {
     analytics,
     i18n,
     theme,
+    userProfile,
   };
 };
 
diff --git a/packages/kbn-management/settings/application/services.tsx b/packages/kbn-management/settings/application/services.tsx
index 26bdc77ef3cea..6384ef0791e51 100644
--- a/packages/kbn-management/settings/application/services.tsx
+++ b/packages/kbn-management/settings/application/services.tsx
@@ -121,6 +121,7 @@ export const SettingsApplicationKibanaProvider: FC<
   const {
     docLinks,
     notifications,
+    userProfile,
     theme,
     i18n,
     settings,
@@ -194,7 +195,7 @@ export const SettingsApplicationKibanaProvider: FC<
 
   return (
     <SettingsApplicationContext.Provider value={services}>
-      <FormKibanaProvider {...{ docLinks, notifications, theme, i18n, settings }}>
+      <FormKibanaProvider {...{ docLinks, notifications, userProfile, theme, i18n, settings }}>
         {children}
       </FormKibanaProvider>
     </SettingsApplicationContext.Provider>
diff --git a/packages/kbn-management/settings/application/tsconfig.json b/packages/kbn-management/settings/application/tsconfig.json
index 182131a7e8714..3ebad4ae3d214 100644
--- a/packages/kbn-management/settings/application/tsconfig.json
+++ b/packages/kbn-management/settings/application/tsconfig.json
@@ -35,5 +35,6 @@
     "@kbn/management-settings-section-registry",
     "@kbn/core-notifications-browser",
     "@kbn/core-chrome-browser",
+    "@kbn/core-user-profile-browser-mocks",
   ]
 }
diff --git a/packages/kbn-management/settings/components/field_input/mocks/context.mock.tsx b/packages/kbn-management/settings/components/field_input/mocks/context.mock.tsx
index 99cac7ae491bb..0e97f40195ee5 100644
--- a/packages/kbn-management/settings/components/field_input/mocks/context.mock.tsx
+++ b/packages/kbn-management/settings/components/field_input/mocks/context.mock.tsx
@@ -13,6 +13,7 @@ import { I18nProvider } from '@kbn/i18n-react';
 import { KibanaRootContextProvider } from '@kbn/react-kibana-context-root';
 import { themeServiceMock } from '@kbn/core-theme-browser-mocks';
 import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks';
+import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
 import { I18nStart } from '@kbn/core-i18n-browser';
 
 import { FieldInputProvider } from '../services';
@@ -20,6 +21,7 @@ import { FieldInputServices } from '../types';
 
 const createRootMock = () => {
   const analytics = analyticsServiceMock.createAnalyticsServiceStart();
+  const userProfile = userProfileServiceMock.createStart();
   const i18n: I18nStart = {
     Context: ({ children }) => <I18nProvider>{children}</I18nProvider>,
   };
@@ -28,6 +30,7 @@ const createRootMock = () => {
     analytics,
     i18n,
     theme,
+    userProfile,
   };
 };
 
diff --git a/packages/kbn-management/settings/components/field_input/tsconfig.json b/packages/kbn-management/settings/components/field_input/tsconfig.json
index d971549abb2d4..d3fc7c27da7a9 100644
--- a/packages/kbn-management/settings/components/field_input/tsconfig.json
+++ b/packages/kbn-management/settings/components/field_input/tsconfig.json
@@ -30,5 +30,6 @@
     "@kbn/core-analytics-browser-mocks",
     "@kbn/core-ui-settings-browser",
     "@kbn/code-editor",
+    "@kbn/core-user-profile-browser-mocks",
   ]
 }
diff --git a/packages/kbn-management/settings/components/field_row/mocks/context.tsx b/packages/kbn-management/settings/components/field_row/mocks/context.tsx
index ef2440a252bb7..a57b9e6d801d5 100644
--- a/packages/kbn-management/settings/components/field_row/mocks/context.tsx
+++ b/packages/kbn-management/settings/components/field_row/mocks/context.tsx
@@ -11,6 +11,7 @@ import React, { ReactChild } from 'react';
 import { I18nProvider } from '@kbn/i18n-react';
 
 import { KibanaRootContextProvider } from '@kbn/react-kibana-context-root';
+import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
 import { themeServiceMock } from '@kbn/core-theme-browser-mocks';
 import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks';
 import { I18nStart } from '@kbn/core-i18n-browser';
@@ -26,10 +27,12 @@ const createRootMock = () => {
     Context: ({ children }) => <I18nProvider>{children}</I18nProvider>,
   };
   const theme = themeServiceMock.createStartContract();
+  const userProfile = userProfileServiceMock.createStart();
   return {
     analytics,
     i18n,
     theme,
+    userProfile,
   };
 };
 
diff --git a/packages/kbn-management/settings/components/field_row/tsconfig.json b/packages/kbn-management/settings/components/field_row/tsconfig.json
index fc77ee13c6dc8..0c1f8e31e4a59 100644
--- a/packages/kbn-management/settings/components/field_row/tsconfig.json
+++ b/packages/kbn-management/settings/components/field_row/tsconfig.json
@@ -30,5 +30,6 @@
     "@kbn/core-theme-browser-mocks",
     "@kbn/core-i18n-browser",
     "@kbn/core-analytics-browser-mocks",
+    "@kbn/core-user-profile-browser-mocks",
   ]
 }
diff --git a/packages/kbn-management/settings/components/form/mocks/context.tsx b/packages/kbn-management/settings/components/form/mocks/context.tsx
index 20ee9b2d12aff..a55abd225f669 100644
--- a/packages/kbn-management/settings/components/form/mocks/context.tsx
+++ b/packages/kbn-management/settings/components/form/mocks/context.tsx
@@ -11,6 +11,7 @@ import React, { ReactChild } from 'react';
 import { I18nProvider } from '@kbn/i18n-react';
 
 import { KibanaRootContextProvider } from '@kbn/react-kibana-context-root';
+import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
 import { themeServiceMock } from '@kbn/core-theme-browser-mocks';
 import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks';
 import { I18nStart } from '@kbn/core-i18n-browser';
@@ -25,10 +26,12 @@ const createRootMock = () => {
     Context: ({ children }) => <I18nProvider>{children}</I18nProvider>,
   };
   const theme = themeServiceMock.createStartContract();
+  const userProfile = userProfileServiceMock.createStart();
   return {
     analytics,
     i18n,
     theme,
+    userProfile,
   };
 };
 
diff --git a/packages/kbn-management/settings/components/form/reload_page_toast.tsx b/packages/kbn-management/settings/components/form/reload_page_toast.tsx
index a6594dc888d9c..25e22fb436adc 100644
--- a/packages/kbn-management/settings/components/form/reload_page_toast.tsx
+++ b/packages/kbn-management/settings/components/form/reload_page_toast.tsx
@@ -15,16 +15,23 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
 import { ToastInput } from '@kbn/core-notifications-browser';
 import { I18nStart } from '@kbn/core-i18n-browser';
 import { ThemeServiceStart } from '@kbn/core-theme-browser';
+import type { UserProfileService } from '@kbn/core-user-profile-browser';
 
 export const DATA_TEST_SUBJ_PAGE_RELOAD_BUTTON = 'pageReloadButton';
 
+interface StartDeps {
+  theme: ThemeServiceStart;
+  i18n: I18nStart;
+  userProfile: UserProfileService;
+}
+
 /**
  * Utility function for returning a {@link ToastInput} for displaying a prompt for reloading the page.
  * @param theme The {@link ThemeServiceStart} contract.
  * @param i18nStart The {@link I18nStart} contract.
  * @returns A toast.
  */
-export const reloadPageToast = (theme: ThemeServiceStart, i18nStart: I18nStart): ToastInput => {
+export const reloadPageToast = (startDeps: StartDeps): ToastInput => {
   return {
     title: i18n.translate('management.settings.form.requiresPageReloadToastDescription', {
       defaultMessage: 'One or more settings require you to reload the page to take effect.',
@@ -43,7 +50,7 @@ export const reloadPageToast = (theme: ThemeServiceStart, i18nStart: I18nStart):
           </EuiButton>
         </EuiFlexItem>
       </EuiFlexGroup>,
-      { i18n: i18nStart, theme }
+      startDeps
     ),
     color: 'success',
     toastLifeTimeMs: 15000,
diff --git a/packages/kbn-management/settings/components/form/services.tsx b/packages/kbn-management/settings/components/form/services.tsx
index 49bd4ef7d6223..05d77191cbdc0 100644
--- a/packages/kbn-management/settings/components/form/services.tsx
+++ b/packages/kbn-management/settings/components/form/services.tsx
@@ -46,7 +46,7 @@ export const FormKibanaProvider: FC<PropsWithChildren<FormKibanaDependencies>> =
   children,
   ...deps
 }) => {
-  const { settings, notifications, docLinks, theme, i18n } = deps;
+  const { settings, notifications, docLinks, ...startDeps } = deps;
 
   const services: Services = {
     saveChanges: (changes, scope: UiSettingsScope) => {
@@ -57,7 +57,7 @@ export const FormKibanaProvider: FC<PropsWithChildren<FormKibanaDependencies>> =
       return Promise.all(arr);
     },
     showError: (message: string) => notifications.toasts.addDanger(message),
-    showReloadPagePrompt: () => notifications.toasts.add(reloadPageToast(theme, i18n)),
+    showReloadPagePrompt: () => notifications.toasts.add(reloadPageToast(startDeps)),
   };
 
   return (
diff --git a/packages/kbn-management/settings/components/form/tsconfig.json b/packages/kbn-management/settings/components/form/tsconfig.json
index 8fbe9249a9538..073882ccf4b48 100644
--- a/packages/kbn-management/settings/components/form/tsconfig.json
+++ b/packages/kbn-management/settings/components/form/tsconfig.json
@@ -34,5 +34,7 @@
     "@kbn/management-settings-utilities",
     "@kbn/core-analytics-browser-mocks",
     "@kbn/core-ui-settings-common",
+    "@kbn/core-user-profile-browser-mocks",
+    "@kbn/core-user-profile-browser",
   ]
 }
diff --git a/packages/kbn-management/settings/components/form/types.ts b/packages/kbn-management/settings/components/form/types.ts
index 7e140823f0c23..76b5f2897540d 100644
--- a/packages/kbn-management/settings/components/form/types.ts
+++ b/packages/kbn-management/settings/components/form/types.ts
@@ -17,6 +17,7 @@ import { I18nStart } from '@kbn/core-i18n-browser';
 import { ThemeServiceStart } from '@kbn/core-theme-browser';
 import { ToastsStart } from '@kbn/core-notifications-browser';
 import { UiSettingsScope } from '@kbn/core-ui-settings-common';
+import { UserProfileService } from '@kbn/core-user-profile-browser';
 
 /**
  * Contextual services used by a {@link Form} component.
@@ -42,6 +43,7 @@ interface KibanaDependencies {
     globalClient: Pick<IUiSettingsClient, 'set'>;
   };
   theme: ThemeServiceStart;
+  userProfile: UserProfileService;
   i18n: I18nStart;
   /** The portion of the {@link ToastsStart} contract used by this component. */
   notifications: {
diff --git a/src/plugins/console/public/types/plugin_dependencies.ts b/src/plugins/console/public/types/plugin_dependencies.ts
index 859bb8a1b1011..3f8d32695777f 100644
--- a/src/plugins/console/public/types/plugin_dependencies.ts
+++ b/src/plugins/console/public/types/plugin_dependencies.ts
@@ -8,7 +8,12 @@
  */
 
 import type { FC } from 'react';
-import type { AnalyticsServiceStart, I18nStart, ThemeServiceStart } from '@kbn/core/public';
+import type {
+  AnalyticsServiceStart,
+  I18nStart,
+  ThemeServiceStart,
+  UserProfileService,
+} from '@kbn/core/public';
 import { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public';
 import { DevToolsSetup } from '@kbn/dev-tools-plugin/public';
 import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
@@ -21,6 +26,7 @@ export interface ConsoleStartServices {
   analytics: Pick<AnalyticsServiceStart, 'reportEvent'>;
   i18n: I18nStart;
   theme: Pick<ThemeServiceStart, 'theme$'>;
+  userProfile: UserProfileService;
 }
 
 export interface AppSetupUIPluginDependencies {
diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts
index 8984243bf04b6..9dde73d2909e0 100644
--- a/src/plugins/dev_tools/public/plugin.ts
+++ b/src/plugins/dev_tools/public/plugin.ts
@@ -66,8 +66,8 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
 
         const [core] = await getStartServices();
         const { application, chrome, executionContext } = core;
-        const { analytics, i18n: i18nStart, theme } = core;
-        const startServices = { analytics, i18n: i18nStart, theme };
+        const { analytics, i18n: i18nStart, theme, userProfile } = core;
+        const startServices = { analytics, i18n: i18nStart, theme, userProfile };
 
         this.docTitleService.setup(chrome.docTitle.change);
         this.breadcrumbService.setup(chrome.setBreadcrumbs);
diff --git a/src/plugins/dev_tools/public/types.ts b/src/plugins/dev_tools/public/types.ts
index aeba759fe31ea..2f729d2a0aac5 100644
--- a/src/plugins/dev_tools/public/types.ts
+++ b/src/plugins/dev_tools/public/types.ts
@@ -7,7 +7,12 @@
  * License v3.0 only", or the "Server Side Public License, v 1".
  */
 
-import { AnalyticsServiceStart, I18nStart, ThemeServiceStart } from '@kbn/core/public';
+import {
+  AnalyticsServiceStart,
+  I18nStart,
+  ThemeServiceStart,
+  UserProfileService,
+} from '@kbn/core/public';
 
 export interface ConfigSchema {
   deeplinks: {
@@ -19,4 +24,5 @@ export interface DevToolsStartServices {
   analytics: Pick<AnalyticsServiceStart, 'reportEvent'>;
   i18n: I18nStart;
   theme: Pick<ThemeServiceStart, 'theme$'>;
+  userProfile: UserProfileService;
 }
diff --git a/src/plugins/guided_onboarding/public/plugin.tsx b/src/plugins/guided_onboarding/public/plugin.tsx
index cc6821af4ea0e..e90a357d24c19 100755
--- a/src/plugins/guided_onboarding/public/plugin.tsx
+++ b/src/plugins/guided_onboarding/public/plugin.tsx
@@ -80,7 +80,7 @@ export class GuidedOnboardingPlugin
     application,
     notifications,
   }: {
-    startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>;
+    startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme' | 'userProfile'>;
     targetDomElement: HTMLElement;
     api: ApiService;
     application: ApplicationStart;
diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx
index 849d8f9eb0341..39e38182ddbeb 100644
--- a/src/plugins/management/public/components/management_app/management_app.tsx
+++ b/src/plugins/management/public/components/management_app/management_app.tsx
@@ -116,7 +116,7 @@ export const ManagementApp = ({ dependencies, history, appBasePath }: Management
   };
 
   return (
-    <KibanaRenderContextProvider i18n={coreStart.i18n} theme={coreStart.theme}>
+    <KibanaRenderContextProvider {...coreStart}>
       <RedirectAppLinks coreStart={dependencies.coreStart}>
         <AppContextProvider value={contextDependencies}>
           <KibanaPageTemplate
diff --git a/x-pack/plugins/cross_cluster_replication/public/app/index.tsx b/x-pack/plugins/cross_cluster_replication/public/app/index.tsx
index 8b9fab7258055..c28cc3d453309 100644
--- a/x-pack/plugins/cross_cluster_replication/public/app/index.tsx
+++ b/x-pack/plugins/cross_cluster_replication/public/app/index.tsx
@@ -23,7 +23,7 @@ import { init as initDocumentation } from './services/documentation_links';
 import { App } from './app';
 import { ccrStore } from './store';
 
-type StartServices = Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>;
+type StartServices = Pick<CoreStart, 'analytics' | 'i18n' | 'theme' | 'userProfile'>;
 
 const AppWithExecutionContext = ({
   history,
diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx
index 72821d6a194ae..10079830455ee 100644
--- a/x-pack/plugins/index_management/public/application/index.tsx
+++ b/x-pack/plugins/index_management/public/application/index.tsx
@@ -47,8 +47,9 @@ export const IndexManagementAppContext: React.FC<IndexManagementAppContextProps>
     analytics,
     i18n,
     theme,
+    userProfile,
   } = core;
-  const startServices = { analytics, i18n, overlays, theme };
+  const startServices = { analytics, i18n, overlays, theme, userProfile };
   const { services, setBreadcrumbs, uiSettings, settings, kibanaVersion } = dependencies;
 
   // theme is required by the CodeEditor component used to edit runtime field Painless scripts.
@@ -61,6 +62,7 @@ export const IndexManagementAppContext: React.FC<IndexManagementAppContextProps>
         get: () => kibanaVersion,
       },
       theme,
+      userProfile,
     });
 
   const componentTemplateProviderValues = {
@@ -122,6 +124,7 @@ interface KibanaReactContextServices {
     get: () => SemVer;
   };
   theme: CoreStart['theme'];
+  userProfile: CoreStart['userProfile'];
 }
 
 // We override useKibana() from the react plugin to return a typed version for this app
diff --git a/x-pack/plugins/index_management/public/types.ts b/x-pack/plugins/index_management/public/types.ts
index c470398c31957..0432feffdf00d 100644
--- a/x-pack/plugins/index_management/public/types.ts
+++ b/x-pack/plugins/index_management/public/types.ts
@@ -10,6 +10,7 @@ import {
   I18nStart,
   OverlayStart,
   ThemeServiceStart,
+  UserProfileService,
 } from '@kbn/core/public';
 import { CloudSetup } from '@kbn/cloud-plugin/public';
 import { ConsolePluginStart } from '@kbn/console-plugin/public';
@@ -24,6 +25,7 @@ export interface IndexManagementStartServices {
   i18n: I18nStart;
   overlays: OverlayStart;
   theme: Pick<ThemeServiceStart, 'theme$'>;
+  userProfile: UserProfileService;
 }
 
 export interface SetupDependencies {
diff --git a/x-pack/plugins/ingest_pipelines/public/application/index.tsx b/x-pack/plugins/ingest_pipelines/public/application/index.tsx
index 9bc3ba7fe27ad..da54113331e68 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/index.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/index.tsx
@@ -53,7 +53,7 @@ export interface AppServices {
   config: Config;
 }
 
-type StartServices = Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>;
+type StartServices = Pick<CoreStart, 'analytics' | 'i18n' | 'theme' | 'userProfile'>;
 
 export interface CoreServices extends StartServices {
   http: HttpSetup;
diff --git a/x-pack/plugins/painless_lab/public/plugin.tsx b/x-pack/plugins/painless_lab/public/plugin.tsx
index 02ff77d5a862d..2579bbe1068cf 100644
--- a/x-pack/plugins/painless_lab/public/plugin.tsx
+++ b/x-pack/plugins/painless_lab/public/plugin.tsx
@@ -51,16 +51,7 @@ export class PainlessLabUIPlugin implements Plugin<void, void, PluginDependencie
       mount: async ({ element }) => {
         const [core] = await getStartServices();
 
-        const {
-          notifications,
-          docLinks,
-          chrome,
-          settings,
-          analytics,
-          i18n: i18nStart,
-          theme,
-        } = core;
-        const startServices = { analytics, i18n: i18nStart, theme };
+        const { notifications, docLinks, chrome, settings, ...startServices } = core;
 
         const license = await firstValueFrom(licensing.license$);
         const licenseStatus = checkLicenseStatus(license);
diff --git a/x-pack/plugins/painless_lab/public/types.ts b/x-pack/plugins/painless_lab/public/types.ts
index 693488860aff0..f870f2aedbfc8 100644
--- a/x-pack/plugins/painless_lab/public/types.ts
+++ b/x-pack/plugins/painless_lab/public/types.ts
@@ -8,7 +8,12 @@
 import { HomePublicPluginSetup } from '@kbn/home-plugin/public';
 import { DevToolsSetup } from '@kbn/dev-tools-plugin/public';
 import { LicensingPluginSetup } from '@kbn/licensing-plugin/public';
-import { AnalyticsServiceStart, I18nStart, ThemeServiceStart } from '@kbn/core/public';
+import {
+  AnalyticsServiceStart,
+  I18nStart,
+  ThemeServiceStart,
+  UserProfileService,
+} from '@kbn/core/public';
 
 export interface PluginDependencies {
   licensing: LicensingPluginSetup;
@@ -20,4 +25,5 @@ export interface PainlessLabStartServices {
   analytics: Pick<AnalyticsServiceStart, 'reportEvent'>;
   i18n: I18nStart;
   theme: Pick<ThemeServiceStart, 'theme$'>;
+  userProfile: UserProfileService;
 }
diff --git a/x-pack/plugins/remote_clusters/public/application/index.d.ts b/x-pack/plugins/remote_clusters/public/application/index.d.ts
index 182cf0ea1b71d..38da9bad7ea46 100644
--- a/x-pack/plugins/remote_clusters/public/application/index.d.ts
+++ b/x-pack/plugins/remote_clusters/public/application/index.d.ts
@@ -17,5 +17,5 @@ export declare const renderApp: (
     canUseAPIKeyTrustModel: boolean;
   },
   history: ScopedHistory,
-  startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>
+  startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme' | 'userProfile'>
 ) => ReturnType<RegisterManagementAppArgs['mount']>;
diff --git a/x-pack/plugins/searchprofiler/public/plugin.ts b/x-pack/plugins/searchprofiler/public/plugin.ts
index 4d8cecaf31381..a1357add7e62f 100644
--- a/x-pack/plugins/searchprofiler/public/plugin.ts
+++ b/x-pack/plugins/searchprofiler/public/plugin.ts
@@ -47,8 +47,7 @@ export class SearchProfilerUIPlugin implements Plugin<void, void, AppPublicPlugi
       enableRouting: false,
       mount: async (params) => {
         const [coreStart] = await getStartServices();
-        const { notifications, analytics, i18n: i18nStart, theme } = coreStart;
-        const startServices = { analytics, i18n: i18nStart, theme };
+        const { notifications, ...startServices } = coreStart;
 
         const { renderApp } = await import('./application');
 
diff --git a/x-pack/plugins/searchprofiler/public/types.ts b/x-pack/plugins/searchprofiler/public/types.ts
index bea00be58bacc..788b2a8693e53 100644
--- a/x-pack/plugins/searchprofiler/public/types.ts
+++ b/x-pack/plugins/searchprofiler/public/types.ts
@@ -9,12 +9,18 @@ import { HomePublicPluginSetup } from '@kbn/home-plugin/public';
 import { DevToolsSetup } from '@kbn/dev-tools-plugin/public';
 import { SharePluginSetup } from '@kbn/share-plugin/public';
 import { LicensingPluginSetup } from '@kbn/licensing-plugin/public';
-import { AnalyticsServiceStart, I18nStart, ThemeServiceStart } from '@kbn/core/public';
+import {
+  AnalyticsServiceStart,
+  I18nStart,
+  ThemeServiceStart,
+  UserProfileService,
+} from '@kbn/core/public';
 
 export interface SearchProfilerStartServices {
   analytics: Pick<AnalyticsServiceStart, 'reportEvent'>;
   i18n: I18nStart;
   theme: Pick<ThemeServiceStart, 'theme$'>;
+  userProfile: UserProfileService;
 }
 
 export interface AppPublicPluginDependencies {
diff --git a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx
index 8b8c19b855bfa..0b216332888ea 100644
--- a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx
+++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx
@@ -48,6 +48,7 @@ export const mockContextValue: AppDeps = {
   toasts: notificationServiceMock.createSetupContract().toasts,
   i18n: coreStart.i18n,
   theme: coreStart.theme,
+  userProfile: coreStart.userProfile,
   chartsTheme: {
     useChartsBaseTheme: jest.fn(),
   } as any,
diff --git a/x-pack/plugins/watcher/public/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx
index 8156fb9a1ca29..a5e9596b2044d 100644
--- a/x-pack/plugins/watcher/public/application/app.tsx
+++ b/x-pack/plugins/watcher/public/application/app.tsx
@@ -16,6 +16,7 @@ import {
   ExecutionContextStart,
   ThemeServiceStart,
   I18nStart,
+  UserProfileService,
 } from '@kbn/core/public';
 import type { SettingsStart } from '@kbn/core-ui-settings-browser';
 
@@ -44,6 +45,7 @@ export interface AppDeps {
   uiSettings: IUiSettingsClient;
   i18n: I18nStart;
   theme: ThemeServiceStart;
+  userProfile: UserProfileService;
   chartsTheme: ChartsPluginSetup['theme'];
   createTimeBuckets: () => any;
   licenseStatus$: Observable<LicenseStatus>;