From bfc4c14760ae3a5a62095c886564ecaab24a319e Mon Sep 17 00:00:00 2001 From: User Date: Fri, 28 Nov 2025 21:17:31 +0530 Subject: [PATCH 1/3] applied theme patches --- patches/ui/theme_and_ui_changes.patch | 1250 +++++++++++++++++++++++++ 1 file changed, 1250 insertions(+) create mode 100644 patches/ui/theme_and_ui_changes.patch diff --git a/patches/ui/theme_and_ui_changes.patch b/patches/ui/theme_and_ui_changes.patch new file mode 100644 index 0000000..48661e8 --- /dev/null +++ b/patches/ui/theme_and_ui_changes.patch @@ -0,0 +1,1250 @@ +diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h +index 59296a7cb076a..c349c59837fe9 100644 +--- a/chrome/browser/ui/color/chrome_color_id.h ++++ b/chrome/browser/ui/color/chrome_color_id.h +@@ -657,6 +657,7 @@ + E_CPONLY(kColorSearchboxResultsForeground) \ + E_CPONLY(kColorSearchboxResultsForegroundDimmed) \ + E_CPONLY(kColorSearchboxResultsIcon) \ ++ E_CPONLY(kColorSearchboxResultsIconContainerBackground) \ + E_CPONLY(kColorSearchboxResultsIconFocusedOutline) \ + E_CPONLY(kColorSearchboxResultsIconSelected) \ + E_CPONLY(kColorSearchboxResultsUrl) \ +diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc +index d6f02fceb7ee8..9446c65b4d2cf 100644 +--- a/chrome/browser/ui/color/chrome_color_mixer.cc ++++ b/chrome/browser/ui/color/chrome_color_mixer.cc +@@ -192,9 +192,9 @@ void AddChromeColorMixer(ui::ColorProvider* provider, + mixer[kColorExtensionsMenuContainerBackground] = {ui::kColorSysSurface3}; + mixer[kColorFeatureFirstRunInfoContainerBackground] = {ui::kColorSysSurface3}; + mixer[kColorFeatureFirstRunIconColor] = {ui::kColorSysOnSurfaceSubtle}; +- mixer[kColorFeaturePromoBubbleBackground] = {gfx::kGoogleBlue700}; ++ mixer[kColorFeaturePromoBubbleBackground] = {dark_mode ? SK_ColorWHITE : SK_ColorBLACK}; + mixer[kColorFeaturePromoBubbleButtonBorder] = {gfx::kGoogleGrey300}; +- mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {gfx::kGoogleBlue300}; ++ mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {dark_mode ? SK_ColorBLACK : SK_ColorWHITE}; + mixer[kColorFeaturePromoBubbleDefaultButtonBackground] = { + kColorFeaturePromoBubbleForeground}; + mixer[kColorFeaturePromoBubbleDefaultButtonForeground] = { +diff --git a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc +index b2b1a40d80524..18cf4a075b8f2 100644 +--- a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc +@@ -53,7 +53,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + ui::kColorSysStateHoverOnSubtle}; + mixer[kColorNewTabPageButtonForeground] = {ui::kColorSysOnTonalContainer}; + +- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; ++ mixer[kColorComposeboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; + mixer[kColorComposeboxFont] = { + dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) +@@ -103,8 +105,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + : SkColorSetRGB(0xAD, 0xAF, 0xB8)}; + mixer[kColorComposeboxFileChipBackground] = {kColorSysSurface3_Light}; + mixer[kColorComposeboxFileChipFaviconBackground] = {kColorSysSurface_Light}; +- mixer[kColorComposeboxFileChipText] = { +- SkColorSetRGB(0x1F, 0x1F, 0x1F)}; ++ mixer[kColorComposeboxFileChipText] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : SkColorSetRGB(0x1F, 0x1F, 0x1F)}; + mixer[kColorComposeboxPdfChipIcon] = { + dark_mode ? SkColorSetRGB(0xAD, 0xAF, 0xB8) + : SkColorSetRGB(0x56, 0x59, 0x5E)}; +@@ -219,12 +222,20 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + ui::kColorSysOnPrimary}; + if (base::FeatureList::IsEnabled(ntp_features::kRealboxCr23Theming)) { + // Steady state theme colors. +- mixer[kColorSearchboxBackground] = {kColorToolbarBackgroundSubtleEmphasis}; ++ mixer[kColorSearchboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(kColorToolbarBackgroundSubtleEmphasis)}; ++ mixer[kColorSearchboxPlaceholder] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxTextDimmed)}; ++ mixer[kColorSearchboxSearchIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxLensVoiceIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(ui::kColorSysPrimary)}; + mixer[kColorSearchboxBackgroundHovered] = { + kColorToolbarBackgroundSubtleEmphasisHovered}; +- mixer[kColorSearchboxPlaceholder] = {kColorOmniboxTextDimmed}; +- mixer[kColorSearchboxSearchIconBackground] = {kColorOmniboxResultsIcon}; +- mixer[kColorSearchboxLensVoiceIconBackground] = {ui::kColorSysPrimary}; + mixer[kColorSearchboxSelectionBackground] = { + kColorOmniboxSelectionBackground}; + mixer[kColorSearchboxSelectionForeground] = { +@@ -235,42 +246,56 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + kColorOmniboxAnswerIconGM3Background}; + mixer[kColorSearchboxAnswerIconForeground] = { + kColorOmniboxAnswerIconGM3Foreground}; +- mixer[kColorSearchboxForeground] = {kColorOmniboxText}; + mixer[kColorSearchboxResultsActionChip] = {ui::kColorSysTonalOutline}; + mixer[kColorSearchboxResultsActionChipIcon] = {ui::kColorSysPrimary}; + mixer[kColorSearchboxResultsActionChipFocusOutline] = { + ui::kColorSysStateFocusRing}; +- mixer[kColorSearchboxResultsBackgroundHovered] = { +- kColorOmniboxResultsBackgroundHovered}; +- mixer[kColorSearchboxResultsButtonHover] = { +- kColorOmniboxResultsButtonInkDropRowHovered}; +- mixer[kColorSearchboxResultsDimSelected] = { +- kColorOmniboxResultsTextDimmedSelected}; + mixer[kColorSearchboxResultsFocusIndicator] = { + kColorOmniboxResultsFocusIndicator}; +- mixer[kColorSearchboxResultsForeground] = {kColorOmniboxText}; +- mixer[kColorSearchboxResultsForegroundDimmed] = {kColorOmniboxTextDimmed}; +- mixer[kColorSearchboxResultsIcon] = {kColorOmniboxResultsIcon}; +- mixer[kColorSearchboxResultsIconSelected] = {kColorOmniboxResultsIcon}; + mixer[kColorSearchboxResultsIconFocusedOutline] = { + kColorOmniboxResultsButtonIconSelected}; +- mixer[kColorSearchboxResultsUrl] = {kColorOmniboxResultsUrl}; +- mixer[kColorSearchboxResultsUrlSelected] = { +- kColorOmniboxResultsUrlSelected}; ++ ++ mixer[kColorSearchboxForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(kColorOmniboxText)}; ++ mixer[kColorSearchboxResultsBackgroundHovered] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsBackgroundHovered)}; ++ mixer[kColorSearchboxResultsButtonHover] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsButtonInkDropRowHovered)}; ++ mixer[kColorSearchboxResultsDimSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsTextDimmedSelected)}; ++ mixer[kColorSearchboxResultsForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(kColorOmniboxText)}; ++ mixer[kColorSearchboxResultsForegroundDimmed] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxTextDimmed)}; ++ mixer[kColorSearchboxResultsIcon] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxResultsIconContainerBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxResultsIconSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxResultsUrl] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : ui::ColorTransform(kColorOmniboxResultsUrl)}; ++ mixer[kColorSearchboxResultsUrlSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : ui::ColorTransform(kColorOmniboxResultsUrlSelected)}; + mixer[kColorSearchboxShadow] = + ui::SetAlpha(gfx::kGoogleGrey900, + (dark_mode ? /* % opacity */ 0.32 : 0.1) * SK_AlphaOPAQUE); + +- // This determines weather the realbox expanded state background in dark +- // mode will match the omnibox or not. +- if (dark_mode && +- !ntp_features::kNtpRealboxCr23ExpandedStateBgMatchesOmnibox.Get()) { +- mixer[kColorSearchboxResultsBackground] = { +- kColorToolbarBackgroundSubtleEmphasis}; +- } else { +- mixer[kColorSearchboxResultsBackground] = { +- kColorOmniboxResultsBackground}; +- } ++ // Use base container color for searchbox results background in dark mode, omnibox color in light mode ++ mixer[kColorSearchboxResultsBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(kColorOmniboxResultsBackground)}; + } + + /* NewTabFooter */ +diff --git a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc +index 8d99d0d5e526e..0a06f2f6d7a0d 100644 +--- a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc ++++ b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc +@@ -27,8 +27,9 @@ void AddMaterialTabStripColorMixer(ui::ColorProvider* provider, + + // TODO(crbug.com/40883407): Validate final mappings for ChromeRefresh23 + // color. ++ const bool dark_mode = key.color_mode == ui::ColorProviderKey::ColorMode::kDark; + ui::ColorMixer& mixer = provider->AddMixer(); +- mixer[kColorTabBackgroundActiveFrameActive] = {ui::kColorSysBase}; ++ mixer[kColorTabBackgroundActiveFrameActive] = {dark_mode ? ui::kColorSysBaseContainer : ui::kColorSysSurface}; + mixer[kColorTabBackgroundActiveFrameInactive] = { + kColorTabBackgroundActiveFrameActive}; + +diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +index 558cc275c8847..350f052b92aef 100644 +--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +@@ -314,7 +314,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + ui::SelectBasedOnDarkInput(kColorNewTabPageAddShortcutBackground, + SK_ColorWHITE, gfx::kGoogleGrey900); + +- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; ++ mixer[kColorComposeboxBackground] = {dark_mode ? ui::kColorSysBaseContainer : SK_ColorWHITE}; + mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; + mixer[kColorComposeboxFont] = { + dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) +@@ -400,15 +400,28 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + SkColorSetRGB(0xD3, 0xE3, 0xFD)}; + mixer[kColorSearchboxAnswerIconForeground] = { + SkColorSetRGB(0x04, 0x1E, 0x49)}; +- mixer[kColorSearchboxBackground] = {SK_ColorWHITE}; +- mixer[kColorSearchboxBackgroundHovered] = {SK_ColorWHITE}; ++ mixer[kColorSearchboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxBackgroundHovered] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(SK_ColorBLACK)}; ++ mixer[kColorSearchboxPlaceholder] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxLensVoiceIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorSearchboxBorder] = { + key.contrast_mode == ui::ColorProviderKey::ContrastMode::kHigh + ? kColorLocationBarBorder + : gfx::kGoogleGrey300}; +- mixer[kColorSearchboxForeground] = {SK_ColorBLACK}; +- mixer[kColorSearchboxPlaceholder] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsBackground] = {SK_ColorWHITE}; + mixer[kColorSearchboxResultsBackgroundHovered] = + ui::SetAlpha(gfx::kGoogleGrey900, + /* 10% opacity */ 0.1 * SK_AlphaOPAQUE); +@@ -420,16 +433,39 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + SkColorSetRGB(0x0B, 0x57, 0xD0)}; + mixer[kColorSearchboxResultsActionChipFocusOutline] = { + SkColorSetRGB(0x0B, 0x57, 0xD0)}; +- mixer[kColorSearchboxResultsDimSelected] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsFocusIndicator] = {gfx::kGoogleBlue600}; +- mixer[kColorSearchboxResultsForeground] = {SK_ColorBLACK}; +- mixer[kColorSearchboxResultsForegroundDimmed] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIconSelected] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsUrl] = {gfx::kGoogleBlue700}; +- mixer[kColorSearchboxResultsUrlSelected] = {gfx::kGoogleBlue700}; +- mixer[kColorSearchboxSearchIconBackground] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIcon] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIconFocusedOutline] = {gfx::kGoogleBlue600}; ++ mixer[kColorSearchboxResultsDimSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsFocusIndicator] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue600}; ++ mixer[kColorSearchboxResultsForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(SK_ColorBLACK)}; ++ mixer[kColorSearchboxResultsForegroundDimmed] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconContainerBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxResultsUrl] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue700}; ++ mixer[kColorSearchboxResultsUrlSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue700}; ++ mixer[kColorSearchboxSearchIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIcon] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconFocusedOutline] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue600}; + mixer[kColorSearchboxShadow] = + ui::SetAlpha(gfx::kGoogleGrey900, + (dark_mode ? /* % opacity */ 0.32 : 0.28) * SK_AlphaOPAQUE); +diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc +index 4e5901f95885b..8617e0e7afe91 100644 +--- a/chrome/browser/ui/layout_constants.cc ++++ b/chrome/browser/ui/layout_constants.cc +@@ -29,7 +29,7 @@ int GetLayoutConstant(LayoutConstant constant) { + case BOOKMARK_BAR_HEIGHT: { + // The fixed margin ensures the bookmark buttons appear centered relative + // to the white space above and below. +- const int bookmark_bar_attached_vertical_margin = 6; ++ const int bookmark_bar_attached_vertical_margin = 10; + return GetLayoutConstant(BOOKMARK_BAR_BUTTON_HEIGHT) + + bookmark_bar_attached_vertical_margin; + } +@@ -93,12 +93,12 @@ int GetLayoutConstant(LayoutConstant constant) { + case TAB_CLOSE_BUTTON_SIZE: + return touch_ui ? 24 : 16; + case TAB_HEIGHT: +- return 34 + GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP); ++ return 36 + GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP); + case TAB_STRIP_HEIGHT: + return GetLayoutConstant(TAB_HEIGHT) + + GetLayoutConstant(TAB_STRIP_PADDING); + case TAB_STRIP_PADDING: +- return 6; ++ return 4; + case TAB_SEPARATOR_HEIGHT: + return touch_ui ? 24 : 20; + case TAB_PRE_TITLE_PADDING: +diff --git a/chrome/browser/ui/tabs/tab_style.cc b/chrome/browser/ui/tabs/tab_style.cc +index eb6789e6212b6..a3894efb96e6a 100644 +--- a/chrome/browser/ui/tabs/tab_style.cc ++++ b/chrome/browser/ui/tabs/tab_style.cc +@@ -27,8 +27,8 @@ constexpr int kChromeRefreshSeparatorHeight = 16; + constexpr int kChromeRefreshTabVerticalPadding = 6; + constexpr int kChromeRefreshTabHorizontalPadding = 8; + +-// The standard tab width is 232 DIP, excluding separators and overlap. +-constexpr int kTabWidth = 232; ++// The standard tab width is 200 DIP, excluding separators and overlap. ++constexpr int kTabWidth = 200; + + } // namespace + +diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc +index 2934bdcab48bb..9aa1eaf769176 100644 +--- a/chrome/browser/ui/toolbar/app_menu_model.cc ++++ b/chrome/browser/ui/toolbar/app_menu_model.cc +@@ -2241,7 +2241,7 @@ bool AppMenuModel::AddDefaultBrowserMenuItems() { + IDC_SET_BROWSER_AS_DEFAULT, + l10n_util::GetStringUTF16(IDS_SET_BROWSER_AS_DEFAULT_MENU_ITEM), + ui::ImageModel::FromVectorIcon(omnibox::kProductChromeRefreshIcon, +- ui::kColorMenuIcon, kDefaultIconSize)); ++ ui::kColorMenuIconOnEmphasizedBackground, kDefaultIconSize)); + SetElementIdentifierAt(GetItemCount() - 1, + AppMenuModel::kSetBrowserAsDefaultMenuItem); + return true; +diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +index a00e5c202067f..ba59857e8378a 100644 +--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc ++++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +@@ -708,26 +708,7 @@ void BookmarkBarView::Layout(PassKey) { + + const int button_height = GetLayoutConstant(BOOKMARK_BAR_BUTTON_HEIGHT); + +- // Bookmark bar buttons should be centered between the bottom of the location +- // bar and the bottom of the bookmarks bar, which requires factoring in the +- // bottom margin of the toolbar into the button position. +- int toolbar_bottom_margin = 0; +- // Note: |browser_view_| may be null during tests. +- if (browser_view_ && !browser_view_->IsFullscreen()) { +- toolbar_bottom_margin = +- browser_view_->toolbar()->height() - +- browser_view_->GetLocationBarView()->bounds().bottom(); +- } +- // Center the buttons in the total available space. +- const int total_height = GetContentsBounds().height() + toolbar_bottom_margin; +- const auto center_y = [total_height, toolbar_bottom_margin](int height) { +- const int top_margin = (total_height - height) / 2; +- // Calculate the top inset in the bookmarks bar itself (not counting the +- // space in the toolbar) but do not allow the buttons to leave the bookmarks +- // bar. +- return std::max(0, top_margin - toolbar_bottom_margin); +- }; +- const int y = center_y(button_height); ++ const int y = 5; + + gfx::Size all_bookmarks_pref = all_bookmarks_button_->GetVisible() + ? all_bookmarks_button_->GetPreferredSize() +@@ -835,7 +816,7 @@ void BookmarkBarView::Layout(PassKey) { + gfx::Size saved_tab_groups_separator_view_pref = + saved_tab_groups_separator_view_->GetPreferredSize(); + saved_tab_groups_separator_view_->SetBounds( +- x, center_y(saved_tab_groups_separator_view_pref.height()), ++ x, 5 + (button_height - saved_tab_groups_separator_view_pref.height()) / 2, + saved_tab_groups_separator_view_pref.width(), + saved_tab_groups_separator_view_pref.height()); + +@@ -905,7 +886,7 @@ void BookmarkBarView::Layout(PassKey) { + // Bookmarks Separator. + if (bookmarks_separator_view_->GetVisible()) { + bookmarks_separator_view_->SetBounds( +- x, center_y(bookmarks_separator_pref.height()), ++ x, 5 + (button_height - bookmarks_separator_pref.height()) / 2, + bookmarks_separator_pref.width(), bookmarks_separator_pref.height()); + + x += bookmarks_separator_pref.width(); +@@ -1107,6 +1088,11 @@ views::View::DropCallback BookmarkBarView::GetDropCallback( + + void BookmarkBarView::OnThemeChanged() { + views::AccessiblePaneView::OnThemeChanged(); ++ if (GetColorProvider()) { ++ SetBorder(views::CreateSolidSidedBorder( ++ gfx::Insets::TLBR(1, 0, 0, 0), ++ GetColorProvider()->GetColor(kColorToolbarSeparator))); ++ } + UpdateAppearanceForTheme(); + } + +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc +index da82293cba539..2dbe7d318cd7b 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc +@@ -20,7 +20,6 @@ + #include "build/build_config.h" + #include "chrome/app/chrome_command_ids.h" + #include "chrome/app/vector_icons/vector_icons.h" +-#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h" + #include "chrome/browser/browser_process.h" + #include "chrome/browser/command_updater.h" + #include "chrome/browser/content_settings/host_content_settings_map_factory.h" +@@ -41,6 +40,7 @@ + #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h" + #include "chrome/browser/ui/browser.h" + #include "chrome/browser/ui/browser_actions.h" ++#include "chrome/browser/ui/browser_commands.h" + #include "chrome/browser/ui/browser_element_identifiers.h" + #include "chrome/browser/ui/browser_finder.h" + #include "chrome/browser/ui/browser_window.h" +@@ -465,21 +465,7 @@ void LocationBarView::Init() { + // |browser_| may be null when LocationBarView is used for non-Browser windows + // such as PresentationReceiverWindowView, which do not support page actions. + if (browser_) { +- // Page action icons that participate in label animations should be added +- // first so that they appear on the left side of the icon container. +- // TODO(crbug.com/40835681): Improve the ordering heuristics for page action +- // icons and determine a way to handle simultaneous icon animations. +- if (base::FeatureList::IsEnabled(commerce::kProductSpecifications)) { +- params.types_enabled.push_back( +- PageActionIconType::kProductSpecifications); +- } +- params.types_enabled.push_back(PageActionIconType::kDiscounts); +- params.types_enabled.push_back(PageActionIconType::kPriceInsights); +- params.types_enabled.push_back(PageActionIconType::kPriceTracking); +- +- if (optimization_guide::features::ShouldEnableOptimizationGuideIconView()) { +- params.types_enabled.push_back(PageActionIconType::kOptimizationGuide); +- } ++ // Keep only essential page action icons, removing Google-specific features + params.types_enabled.push_back(PageActionIconType::kClickToCall); + params.types_enabled.push_back(PageActionIconType::kAutofillAddress); + params.types_enabled.push_back(PageActionIconType::kManagePasswords); +@@ -491,7 +477,6 @@ void LocationBarView::Init() { + params.types_enabled.push_back(PageActionIconType::kTranslate); + params.types_enabled.push_back(PageActionIconType::kZoom); + params.types_enabled.push_back(PageActionIconType::kFileSystemAccess); +- + params.types_enabled.push_back(PageActionIconType::kCookieControls); + params.types_enabled.push_back( + PageActionIconType::kPaymentsOfferNotification); +@@ -503,54 +488,6 @@ void LocationBarView::Init() { + params.types_enabled.push_back(PageActionIconType::kVirtualCardEnroll); + params.types_enabled.push_back(PageActionIconType::kMandatoryReauth); + +- if (browser_ && lens::features::IsOmniboxEntryPointEnabled()) { +- // The persistent compact entrypoint should be positioned directly before +- // the star icon and the prominent expanding entrypoint should be +- // positioned in the leading position. This entrypoint will be suppressed +- // if the AIM page action is enabled and the user meets AIM eligibility +- // criteria, since we want to avoid both showing up when the user focuses +- // the Omnibox. +- if (lens::features::IsOmniboxEntrypointAlwaysVisible()) { +- params.types_enabled.push_back(PageActionIconType::kLensOverlay); +- } else { +- params.types_enabled.insert(params.types_enabled.begin(), +- PageActionIconType::kLensOverlay); +- } +- } +- +- if (browser_ && lens::features::IsLensOverlayEduActionChipEnabled()) { +- // Position in the leading position, like the expanding entrypoint for +- // kLensOverlay above. While both chips may be enabled, they will not appear +- // at the same time due to different focus behavior. +- params.types_enabled.insert(params.types_enabled.begin(), +- PageActionIconType::kLensOverlayHomework); +- } +- +- // Because the AIM eligibility service might not be ready on startup, +- // the AI Mode page action type is always added. Unless the main AIM +- // omnibox entrypoint Feature is explicitly disabled, which can be used +- // as a kill switch in case of any unanticipated issues with this +- // approach. +- auto* feature_list = base::FeatureList::GetInstance(); +- bool aim_omnibox_entrypoint_explicitly_disabled = +- feature_list && +- feature_list->IsFeatureOverridden( +- omnibox::kAiModeOmniboxEntryPoint.name) && +- !base::FeatureList::IsEnabled(omnibox::kAiModeOmniboxEntryPoint); +- if (!aim_omnibox_entrypoint_explicitly_disabled) { +- // Position in the leading position, like the entrypoint for +- // kLensOverlayHomework above. While both chips may be enabled, they will +- // not appear at the same time due to different focus behavior. The +- // visibility of this entrypoint is dependent on whether or not the user +- // meets AIM eligibility criteria. +- params.types_enabled.insert(params.types_enabled.begin(), +- PageActionIconType::kAiMode); +- } +- +- if (browser_ && tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) { +- params.types_enabled.push_back(PageActionIconType::kCollaborationMessaging); +- } +- + if (browser_ && !is_popup_mode_) { + params.types_enabled.push_back(PageActionIconType::kBookmarkStar); + } +@@ -566,17 +503,6 @@ void LocationBarView::Init() { + AddChildView(std::make_unique(params)); + page_action_icon_controller_ = page_action_icon_container_->controller(); + +- if (!page_action_icon_container_->children().empty() && +- !aim_omnibox_entrypoint_explicitly_disabled && +- !IsPageActionMigrated(PageActionIconType::kAiMode)) { +- auto* first_page_action_icon_view = static_cast( +- page_action_icon_container_->children().front()); +- DCHECK(first_page_action_icon_view->action_id() == kActionAiMode) +- << "kActionAiMode must be the first child in " +- "PageActionIconContainerView to ensure it's the left-most page " +- "action."; +- } +- + auto clear_all_button = views::CreateVectorImageButton(base::BindRepeating( + static_cast( + &OmniboxView::SetUserText), +@@ -586,6 +512,22 @@ void LocationBarView::Init() { + clear_all_button_ = AddChildView(std::move(clear_all_button)); + RefreshClearAllButtonIcon(); + ++ // Add copy URL button ++ auto copy_url_button = views::CreateVectorImageButton(base::BindRepeating( ++ [](Browser* browser) { ++ if (browser) { ++ chrome::ExecuteCommand(browser, IDC_COPY_URL); ++ } ++ }, ++ base::Unretained(browser_))); ++ copy_url_button->SetTooltipText( ++ l10n_util::GetStringUTF16(IDS_COPY_URL)); ++ copy_url_button->SetImageModel( ++ views::Button::STATE_NORMAL, ++ ui::ImageModel::FromVectorIcon(kLinkChromeRefreshIcon, kColorOmniboxResultsIcon, ++ GetLayoutConstant(LOCATION_BAR_ICON_SIZE))); ++ copy_url_button_ = AddChildView(std::move(copy_url_button)); ++ + // Initialize the location entry. We do this to avoid a black flash which is + // visible when the location entry has just been initialized. + Update(nullptr); +@@ -963,25 +905,9 @@ void LocationBarView::Layout(PassKey) { + } + }; + +- // When the AIM page action is shown as the right-most page action in the +- // location bar, it should be positioned flush against the right edge of the +- // location bar. +- // If all page actions are migrated (i.e. up to bookmark star), then the extra +- // padding that is usually added to bridge the new and legacy containers can +- // be discounted. +- const bool all_page_actions_migrated = +- IsPageActionMigrated(PageActionIconType::kBookmarkStar); +- const int kTrailingEdgePaddingForAim = +- IsPageActionMigrated(PageActionIconType::kAiMode) && +- !all_page_actions_migrated +- ? -3 +- : 5; + add_trailing_decoration(page_action_icon_container_, + /*intra_item_padding=*/0, +- /*edge_padding=*/ +- IsAimLastVisiblePageAction() +- ? kTrailingEdgePaddingForAim +- : trailing_decorations_edge_padding); ++ /*edge_padding=*/trailing_decorations_edge_padding); + add_trailing_decoration(page_action_container_, + /*intra_item_padding=*/0, + /*edge_padding=*/trailing_decorations_edge_padding); +@@ -1000,6 +926,9 @@ void LocationBarView::Layout(PassKey) { + add_trailing_decoration(clear_all_button_, /*intra_item_padding=*/0, + /*edge_padding=*/trailing_decorations_edge_padding); + ++ add_trailing_decoration(copy_url_button_, /*intra_item_padding=*/0, ++ /*edge_padding=*/trailing_decorations_edge_padding); ++ + // Perform layout. + int entry_width = width(); + +@@ -1272,6 +1201,11 @@ bool LocationBarView::ShouldHidePageActionIcons() const { + + bool LocationBarView::ShouldHidePageActionIcon( + PageActionIconView* icon_view) const { ++ // Bookmark star should always be visible ++ if (page_action_icon_controller_->GetIconType(icon_view) == PageActionIconType::kBookmarkStar) { ++ return false; ++ } ++ + if (ShouldHidePageActionIcons()) { + return true; + } +@@ -1294,25 +1228,8 @@ bool LocationBarView::ShouldHidePageActionIcon( + + bool LocationBarView::ShouldHidePageActionIconsForContext( + metrics::OmniboxEventProto::PageClassification page_context) const { +- switch (page_context) { +- case metrics::OmniboxEventProto:: +- INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS: { +- // When the user is on the NTP and the AIM page action is eligible to be +- // shown, suppress all other page actions in order to minimize UI +- // instability when going from the steady-state to the on-focus Omnibox. +- const auto* aim_eligibility_service = +- AimEligibilityServiceFactory::GetForProfile(profile_); +- const bool is_aim_page_action_enabled = +- OmniboxFieldTrial::IsAimOmniboxEntrypointEnabled( +- aim_eligibility_service); +- const bool hide_other_page_actions_on_ntp = +- omnibox_feature_configs::AiModeOmniboxEntryPoint::Get() +- .hide_other_page_actions_on_ntp; +- return is_aim_page_action_enabled && hide_other_page_actions_on_ntp; +- } +- default: +- return false; +- } ++ // AI Mode removed - no special hiding logic needed ++ return false; + } + + /* +@@ -1361,42 +1278,7 @@ bool LocationBarView::ShouldHidePageActionIconsForContext( + * of how many migrated page actions are visible). + */ + bool LocationBarView::IsAimLastVisiblePageAction() const { +- int visible_migrated_page_action_count = 0; +- bool migrated_aim_page_action_is_visible = false; +- +- // Check PageActionContainerView (migrated page actions). +- for (views::View* view : page_action_container_->children()) { +- if (view->GetVisible()) { +- visible_migrated_page_action_count++; +- page_actions::PageActionView* page_action_view = +- static_cast(view); +- if (page_action_view->GetActionId() == kActionAiMode) { +- migrated_aim_page_action_is_visible = true; +- } +- } +- } +- +- int visible_page_action_count = 0; +- bool aim_page_action_is_visible = false; +- +- // Check PageActionIconContainerView (legacy page actions). +- for (views::View* view : page_action_icon_container_->children()) { +- if (view->GetVisible()) { +- visible_page_action_count++; +- PageActionIconView* icon_view = static_cast(view); +- if (icon_view->action_id() == kActionAiMode) { +- aim_page_action_is_visible = true; +- } +- } +- } +- +- if (migrated_aim_page_action_is_visible && +- (visible_migrated_page_action_count + visible_page_action_count) == 1) { +- return true; +- } else if (aim_page_action_is_visible && visible_page_action_count == 1) { +- return true; +- } +- ++ // AI Mode removed - always return false + return false; + } + +@@ -1466,9 +1348,9 @@ void LocationBarView::RefreshBackground() { + ui::NativeTheme::PreferredContrast::kMore; + + const auto* const color_provider = GetColorProvider(); +- SkColor normal = color_provider->GetColor(kColorLocationBarBackground); ++ SkColor normal = color_provider->GetColor(kColorToolbar); + SkColor hovered = +- color_provider->GetColor(kColorLocationBarBackgroundHovered); ++ color_provider->GetColor(kColorToolbar); + + background_color_ = gfx::Tween::ColorValueBetween(opacity, normal, hovered); + if (is_caret_visible) { +@@ -1565,20 +1447,7 @@ void LocationBarView::RefreshPageActionIconViews() { + } + + void LocationBarView::RefreshAiModePageActionIconView() { +- if (IsPageActionMigrated(PageActionIconType::kAiMode)) { +- auto* aim_page_action_controller = +- omnibox::AiModePageActionController::From(browser_); +- if (aim_page_action_controller) { +- aim_page_action_controller->UpdatePageAction(); +- } +- return; +- } +- +- PageActionIconView* aim_icon_view = +- page_action_icon_controller_->GetIconView(PageActionIconType::kAiMode); +- if (aim_icon_view) { +- aim_icon_view->Update(); +- } ++ // AI Mode removed - no-op + } + + void LocationBarView::RefreshPageActionContainerViewAndIconsVisibility( +@@ -1912,13 +1781,12 @@ void LocationBarView::OnChanged() { + !omnibox_view_->GetText().empty() && + IsVirtualKeyboardVisible(GetWidget())); + ++ // Copy URL button is always visible ++ copy_url_button_->SetVisible(true); ++ + InvalidateLayout(); + SchedulePaint(); + UpdateChipVisibility(); +- // The AI mode page action icon view visibility depends on whether or not +- // user text has been entered into the omnibox, so refresh the icon on +- // changes. +- RefreshAiModePageActionIconView(); + } + + const LocationBarModel* LocationBarView::GetLocationBarModel() const { +@@ -1934,10 +1802,6 @@ void LocationBarView::OnOmniboxFocused() { + // the omnibox is intentional, snapping is better than transitioning here. + hover_animation_.Reset(); + RefreshBackground(); +- +- // The AI mode page action icon view should only be visible when the omnibox +- // is focused, so if there is a change in focus, refresh the icon. +- RefreshAiModePageActionIconView(); + } + + void LocationBarView::OnOmniboxBlurred() { +@@ -1946,10 +1810,6 @@ void LocationBarView::OnOmniboxBlurred() { + } + RefreshBackground(); + +- // The AI mode page action icon view should only be visible when the omnibox +- // is focused, so if there is a change in focus, refresh the icon. +- RefreshAiModePageActionIconView(); +- + location_icon_view_->Update(false, false); + } + +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h +index 507ca6272a7b1..7993f100b5281 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.h ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.h +@@ -570,6 +570,9 @@ class LocationBarView + // user to clear all text. + raw_ptr clear_all_button_ = nullptr; + ++ // A button to copy the current URL to clipboard. ++ raw_ptr copy_url_button_ = nullptr; ++ + // Animation to change whole location bar background color on hover. + gfx::SlideAnimation hover_animation_{this}; + +diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc +index 93a656042af50..d5306a85b1e0c 100644 +--- a/chrome/browser/ui/views/tabs/tab.cc ++++ b/chrome/browser/ui/views/tabs/tab.cc +@@ -1167,10 +1167,10 @@ void Tab::UpdateIconVisibility() { + #if BUILDFLAG(IS_CHROMEOS) + // Hide tab close button for OnTask if locked. Only applicable for non-web + // browser scenarios. +- showing_close_button_ = !controller_->IsLockedForOnTask(); ++ showing_close_button_ = !controller_->IsLockedForOnTask() && mouse_hovered_; + #else +- // Close button is shown on active tabs regardless of the size. +- showing_close_button_ = true; ++ // Close button is shown on active tabs only when hovered. ++ showing_close_button_ = mouse_hovered_; + #endif // BUILDFLAG(IS_CHROMEOS) + available_width -= close_button_width; + +@@ -1196,11 +1196,12 @@ void Tab::UpdateIconVisibility() { + available_width -= favicon_width; + } + ++ // Only show close button on hover for inactive tabs + showing_close_button_ = + #if BUILDFLAG(IS_CHROMEOS) + !controller_->IsLockedForOnTask() && + #endif +- large_enough_for_close_button; ++ large_enough_for_close_button && mouse_hovered_; + if (showing_close_button_) { + available_width -= close_button_width; + } +diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc +index fe66c423ab248..1346e9de8e2e5 100644 +--- a/chrome/browser/ui/views/tabs/tab_style_views.cc ++++ b/chrome/browser/ui/views/tabs/tab_style_views.cc +@@ -210,8 +210,6 @@ SkPath TabStyleViewsImpl::GetPath(TabStyle::PathType path_type, + CHECK(tab()); + const int stroke_thickness = GetStrokeThickness(flags.force_active); + +- const TabStyle::TabSelectionState state = GetSelectionState(); +- + // We'll do the entire path calculation in aligned pixels. + // TODO(dfried): determine if we actually want to use `stroke_thickness` as + // the inset in this case. +@@ -229,8 +227,8 @@ SkPath TabStyleViewsImpl::GetPath(TabStyle::PathType path_type, + scale; + + // Selected, hover, and inactive tab fills are a detached squarcle tab. +- if ((path_type == TabStyle::PathType::kFill && +- state != TabStyle::TabSelectionState::kActive) || ++ // Active tabs also use this shape for consistent rounded rectangle appearance. ++ if ((path_type == TabStyle::PathType::kFill) || + path_type == TabStyle::PathType::kHighlight || + path_type == TabStyle::PathType::kInteriorClip || + path_type == TabStyle::PathType::kHitTest) { +@@ -1031,8 +1029,8 @@ void TabStyleViewsImpl::PaintBackgroundStroke( + } + + SkPath outer_path = +- GetPath(TabStyle::PathType::kBorder, canvas->image_scale(), +- {.force_active = is_active, .should_paint_extension = false}); ++ GetPath(TabStyle::PathType::kFill, canvas->image_scale(), ++ {.force_active = is_active}); + gfx::ScopedCanvas scoped_canvas(canvas); + float scale = canvas->UndoDeviceScaleFactor(); + cc::PaintFlags flags; +@@ -1063,12 +1061,19 @@ void TabStyleViewsImpl::PaintSeparators(gfx::Canvas* canvas) const { + + cc::PaintFlags flags; + flags.setAntiAlias(true); ++ flags.setStyle(cc::PaintFlags::kStroke_Style); ++ flags.setStrokeWidth(1.0f * scale); ++ ++ // Draw simple vertical lines instead of rounded rectangles + flags.setColor(separator_color(separator_opacities.left)); +- canvas->DrawRoundRect(separator_bounds.leading, +- tab_style()->GetSeparatorCornerRadius() * scale, flags); ++ float left_x = separator_bounds.leading.x() + separator_bounds.leading.width() / 2; ++ canvas->DrawLine(gfx::PointF(left_x, separator_bounds.leading.y()), ++ gfx::PointF(left_x, separator_bounds.leading.bottom()), flags); ++ + flags.setColor(separator_color(separator_opacities.right)); +- canvas->DrawRoundRect(separator_bounds.trailing, +- tab_style()->GetSeparatorCornerRadius() * scale, flags); ++ float right_x = separator_bounds.trailing.x() + separator_bounds.trailing.width() / 2; ++ canvas->DrawLine(gfx::PointF(right_x, separator_bounds.trailing.y()), ++ gfx::PointF(right_x, separator_bounds.trailing.bottom()), flags); + } + + bool TabStyleViewsImpl::IsLeftSplitTab(const Tab* tab) const { +diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc +index d10401dad12b2..da0cca83c497f 100644 +--- a/chrome/browser/ui/views/toolbar/app_menu.cc ++++ b/chrome/browser/ui/views/toolbar/app_menu.cc +@@ -1597,6 +1597,7 @@ void AppMenu::PopulateMenu(MenuItemView* parent, MenuModel* model) { + views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_CONTROL_VERTICAL_TEXT_PADDING), + ui::kColorAppMenuUpgradeRowBackground); ++ item->SetForegroundColorId(ui::kColorAppMenuUpgradeRowSubstringForeground); + } + break; + } +diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc +index 0a324e3999d7a..e86eec19bd872 100644 +--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc ++++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc +@@ -413,6 +413,16 @@ void ToolbarView::Init() { + + location_bar_ = container_view_->AddChildView(std::move(location_bar)); + ++ // Add a divider after the location bar ++ auto location_bar_divider = std::make_unique(); ++ location_bar_divider_ = container_view_->AddChildView(std::move(location_bar_divider)); ++ location_bar_divider_->SetPreferredSize( ++ gfx::Size(GetLayoutConstant(TOOLBAR_DIVIDER_WIDTH), ++ GetLayoutConstant(TOOLBAR_DIVIDER_HEIGHT))); ++ location_bar_divider_->SetBackground(views::CreateRoundedRectBackground( ++ kColorToolbarSeparator, ++ GetLayoutConstant(TOOLBAR_DIVIDER_CORNER_RADIUS))); ++ + if (extensions_container) { + extensions_container_ = + container_view_->AddChildView(std::move(extensions_container)); +@@ -1008,6 +1018,12 @@ void ToolbarView::InitLayout() { + gfx::Insets::VH(0, GetLayoutConstant(TOOLBAR_DIVIDER_SPACING))); + } + ++ if (location_bar_divider_) { ++ location_bar_divider_->SetProperty( ++ views::kMarginsKey, ++ gfx::Insets::VH(0, GetLayoutConstant(TOOLBAR_DIVIDER_SPACING))); ++ } ++ + constexpr int kToolbarFlexOrderStart = 1; + + // TODO(crbug.com/40929989): Ignore containers till issue addressed. +diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h +index 415970aadb0ed..d29a28f80fb0c 100644 +--- a/chrome/browser/ui/views/toolbar/toolbar_view.h ++++ b/chrome/browser/ui/views/toolbar/toolbar_view.h +@@ -295,6 +295,7 @@ class ToolbarView : public views::AccessiblePaneView, + raw_ptr split_tabs_ = nullptr; + raw_ptr custom_tab_bar_ = nullptr; + raw_ptr location_bar_ = nullptr; ++ raw_ptr location_bar_divider_ = nullptr; + raw_ptr extensions_container_ = nullptr; + raw_ptr toolbar_divider_ = nullptr; + raw_ptr battery_saver_button_ = nullptr; +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +index 202099eee781e..832ca90c1538c 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +@@ -583,7 +583,7 @@ void NewTabPageHandler::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterIntegerPref( + prefs::kNtpCustomizeChromeSidePanelAutoOpeningsCount, 0); + registry->RegisterBooleanPref(prefs::kNtpCustomizeChromeExplicitlyClosed, +- false); ++ true); + registry->RegisterBooleanPref(prefs::kNtpCustomizeChromeIPHAutoOpened, false); + } + +diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc +index 406d9402d41e1..6d2ea1d68430b 100644 +--- a/components/search/ntp_features.cc ++++ b/components/search/ntp_features.cc +@@ -98,7 +98,7 @@ BASE_FEATURE(kNtpDummyModules, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, Google Drive module will be shown. + // This is a kill switch. Keep indefinitely. +-BASE_FEATURE(kNtpDriveModule, base::FEATURE_ENABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpDriveModule, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, the NTP Drive module does not require sync. + BASE_FEATURE(kNtpDriveModuleHistorySyncRequirement, +@@ -121,7 +121,7 @@ BASE_FEATURE(kNtpMiddleSlotPromo, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, middle slot promo will be dismissed from New Tab Page until new + // promo message is populated +-BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_ENABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_DISABLED_BY_DEFAULT); + + // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". + // This is used for an emergency Finch param. Keep indefinitely. +diff --git a/ui/color/core_default_color_mixer.cc b/ui/color/core_default_color_mixer.cc +index 54cb33c7e3f91..41446d2a935c5 100644 +--- a/ui/color/core_default_color_mixer.cc ++++ b/ui/color/core_default_color_mixer.cc +@@ -25,7 +25,7 @@ void AddCoreDefaultColorMixer(ColorProvider* provider, + DVLOG(2) << "Adding CoreDefaultColorMixer to ColorProvider for " + << (dark_mode ? "Dark" : "Light") << " window."; + ColorMixer& mixer = provider->AddMixer(); +- mixer[kColorAccent] = {dark_mode ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600}; ++ mixer[kColorAccent] = {dark_mode ? SK_ColorWHITE : SK_ColorWHITE}; + // 4.5 and 7.0 approximate the default light and dark theme contrasts of + // accent-against-primary-background. + mixer[kColorAccentWithGuaranteedContrastAtopPrimaryBackground] = +diff --git a/ui/color/mac/native_color_mixers_mac.mm b/ui/color/mac/native_color_mixers_mac.mm +index fb2d49fe27f3d..c740e3b5fa995 100644 +--- a/ui/color/mac/native_color_mixers_mac.mm ++++ b/ui/color/mac/native_color_mixers_mac.mm +@@ -99,11 +99,11 @@ void AddNativeUiColorMixer(ColorProvider* provider, + + mixer[kColorTableBackgroundAlternate] = {skia::NSSystemColorToSkColor( + NSColor.alternatingContentBackgroundColors[1])}; +- if (!key.user_color.has_value()) { +- mixer[kColorSysStateFocusRing] = PickGoogleColor( +- skia::NSSystemColorToSkColor(NSColor.keyboardFocusIndicatorColor), +- kColorSysBase, color_utils::kMinimumVisibleContrastRatio); + ++ // Override focus ring color: white in dark mode, black in light mode ++ mixer[kColorSysStateFocusRing] = {properties.dark ? SK_ColorWHITE : SK_ColorBLACK}; ++ ++ if (!key.user_color.has_value()) { + const SkColor system_highlight_color = + skia::NSSystemColorToSkColor(NSColor.selectedTextBackgroundColor); + mixer[kColorTextSelectionBackground] = {system_highlight_color}; +diff --git a/ui/color/ref_color_mixer.cc b/ui/color/ref_color_mixer.cc +index 3eb2f1053b895..a57a92344f27a 100644 +--- a/ui/color/ref_color_mixer.cc ++++ b/ui/color/ref_color_mixer.cc +@@ -25,36 +25,36 @@ namespace ui { + void AddBaselinePalette(ColorProvider* provider) { + ColorMixer& mixer = provider->AddMixer(); + mixer[kColorRefPrimary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +- mixer[kColorRefPrimary10] = {SkColorSetRGB(0x04, 0x1E, 0x49)}; +- mixer[kColorRefPrimary20] = {SkColorSetRGB(0x06, 0x2E, 0x6F)}; +- mixer[kColorRefPrimary25] = {SkColorSetRGB(0x07, 0x38, 0x88)}; +- mixer[kColorRefPrimary30] = {SkColorSetRGB(0x08, 0x42, 0xA0)}; +- mixer[kColorRefPrimary40] = {SkColorSetRGB(0x0B, 0x57, 0xD0)}; +- mixer[kColorRefPrimary50] = {SkColorSetRGB(0x1B, 0x6E, 0xF3)}; +- mixer[kColorRefPrimary60] = {SkColorSetRGB(0x4C, 0x8D, 0xF6)}; +- mixer[kColorRefPrimary70] = {SkColorSetRGB(0x7C, 0xAC, 0xF8)}; +- mixer[kColorRefPrimary80] = {SkColorSetRGB(0xA8, 0xC7, 0xFA)}; +- mixer[kColorRefPrimary90] = {SkColorSetRGB(0xD3, 0xE3, 0xFD)}; +- mixer[kColorRefPrimary95] = {SkColorSetRGB(0xEC, 0xF3, 0xFE)}; +- mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFB, 0xFF)}; ++ mixer[kColorRefPrimary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; ++ mixer[kColorRefPrimary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; ++ mixer[kColorRefPrimary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; ++ mixer[kColorRefPrimary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; ++ mixer[kColorRefPrimary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; ++ mixer[kColorRefPrimary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; ++ mixer[kColorRefPrimary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; ++ mixer[kColorRefPrimary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; ++ mixer[kColorRefPrimary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; ++ mixer[kColorRefPrimary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; ++ mixer[kColorRefPrimary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; ++ mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; + mixer[kColorRefPrimary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; + + mixer[kColorRefSecondary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +- mixer[kColorRefSecondary10] = {SkColorSetRGB(0x00, 0x1D, 0x35)}; +- mixer[kColorRefSecondary12] = {SkColorSetRGB(0x00, 0x22, 0x38)}; +- mixer[kColorRefSecondary15] = {SkColorSetRGB(0x00, 0x28, 0x45)}; +- mixer[kColorRefSecondary20] = {SkColorSetRGB(0x00, 0x33, 0x55)}; +- mixer[kColorRefSecondary25] = {SkColorSetRGB(0x00, 0x3f, 0x66)}; +- mixer[kColorRefSecondary30] = {SkColorSetRGB(0x00, 0x4A, 0x77)}; +- mixer[kColorRefSecondary35] = {SkColorSetRGB(0x00, 0x57, 0x89)}; +- mixer[kColorRefSecondary40] = {SkColorSetRGB(0x00, 0x63, 0x9B)}; +- mixer[kColorRefSecondary50] = {SkColorSetRGB(0x04, 0x7D, 0xB7)}; +- mixer[kColorRefSecondary60] = {SkColorSetRGB(0x39, 0x98, 0xD3)}; +- mixer[kColorRefSecondary70] = {SkColorSetRGB(0x5A, 0xB3, 0xF0)}; +- mixer[kColorRefSecondary80] = {SkColorSetRGB(0x7F, 0xCF, 0xFF)}; +- mixer[kColorRefSecondary90] = {SkColorSetRGB(0xC2, 0xE7, 0xFF)}; +- mixer[kColorRefSecondary95] = {SkColorSetRGB(0xDF, 0xF3, 0xFF)}; +- mixer[kColorRefSecondary99] = {SkColorSetRGB(0xF7, 0xFC, 0xFF)}; ++ mixer[kColorRefSecondary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; ++ mixer[kColorRefSecondary12] = {SkColorSetRGB(0x1F, 0x1F, 0x1F)}; ++ mixer[kColorRefSecondary15] = {SkColorSetRGB(0x26, 0x26, 0x26)}; ++ mixer[kColorRefSecondary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; ++ mixer[kColorRefSecondary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; ++ mixer[kColorRefSecondary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; ++ mixer[kColorRefSecondary35] = {SkColorSetRGB(0x59, 0x59, 0x59)}; ++ mixer[kColorRefSecondary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; ++ mixer[kColorRefSecondary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; ++ mixer[kColorRefSecondary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; ++ mixer[kColorRefSecondary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; ++ mixer[kColorRefSecondary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; ++ mixer[kColorRefSecondary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; ++ mixer[kColorRefSecondary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; ++ mixer[kColorRefSecondary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; + mixer[kColorRefSecondary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; + + mixer[kColorRefTertiary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +diff --git a/ui/color/sys_color_mixer.cc b/ui/color/sys_color_mixer.cc +index 4745b7f50a28b..6cef161038ae8 100644 +--- a/ui/color/sys_color_mixer.cc ++++ b/ui/color/sys_color_mixer.cc +@@ -31,6 +31,8 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, + : kColorRefSecondary30}; + mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefPrimary30 + : kColorRefPrimary90}; ++ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; + mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefPrimary10 + : kColorRefPrimary90}; + mixer[kColorSysNeutralContainer] = {dark_mode ? kColorRefNeutralVariant15 +@@ -39,18 +41,18 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, + : kColorRefPrimary90}; + + // Chrome surfaces. +- mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary25 ++ mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary10 + : kColorRefNeutral98}; +- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary15 ++ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary25 + : kColorSysSurface4}; + mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefSecondary25 + : kColorRefNeutral98}; + +- mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary12 ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary10 + : kColorRefSecondary90}; + mixer[kColorSysHeaderContainer] = {dark_mode ? kColorRefSecondary25 + : kColorRefPrimary95}; +- mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral25 ++ mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral99}; + mixer[kColorSysOnHeaderDivider] = {dark_mode ? kColorRefSecondary25 + : kColorRefPrimary80}; +@@ -78,12 +80,12 @@ void AddGrayscaleSysColorOverrides(ColorMixer& mixer, + + // General + mixer[kColorSysOnSurfacePrimary] = {dark_mode ? kColorRefNeutral90 +- : kColorRefNeutral10}; +- mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 +- : kColorRefNeutral90}; ++ : kColorRefNeutral10}; ++mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 ++: kColorRefNeutral90}; + + // Chrome surfaces. +- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral90}; + mixer[kColorSysHeaderInactive] = { + dark_mode ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) +@@ -116,24 +118,24 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + ColorMixer& mixer = provider->AddMixer(); + + // Primary. +- mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary80 +- : kColorRefPrimary40}; +- mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary20 +- : kColorRefPrimary100}; +- mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary30 +- : kColorRefPrimary90}; +- mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary90 +- : kColorRefPrimary10}; ++ mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; ++ mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary10 ++ : kColorRefPrimary90}; ++ mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; ++ mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary10 ++ : kColorRefPrimary90}; + + // Secondary. +- mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary80 +- : kColorRefSecondary40}; +- mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary20 +- : kColorRefSecondary100}; +- mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary30 +- : kColorRefSecondary90}; +- mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary90 +- : kColorRefSecondary10}; ++ mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary90 ++ : kColorRefSecondary10}; ++ mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary10 ++ : kColorRefSecondary90}; ++ mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary90 ++ : kColorRefSecondary10}; ++ mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary10 ++ : kColorRefSecondary90}; + // Tertiary. + mixer[kColorSysTertiary] = {dark_mode ? kColorRefTertiary80 + : kColorRefTertiary40}; +@@ -179,8 +181,8 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + mixer[kColorSysSurface] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral100}; + mixer[kColorSysSurfaceNumberedForeground] = { +- dark_mode ? SkColorSetRGB(0xD1, 0xE1, 0xFF) +- : SkColorSetRGB(0x69, 0x91, 0xD6)}; ++ dark_mode ? kColorRefNeutral90 ++ : kColorRefNeutral10}; + mixer[kColorSysSurface1] = AlphaBlend({kColorSysSurfaceNumberedForeground}, + {kColorSysSurface}, 0x0C); + mixer[kColorSysSurface2] = AlphaBlend({kColorSysSurfaceNumberedForeground}, +@@ -202,10 +204,10 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + mixer[kColorSysOnSurfacePrimaryInactive] = {dark_mode ? kColorRefNeutral90 + : kColorRefNeutral10}; + +- mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary30 +- : kColorRefPrimary90}; +- mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary90 +- : kColorRefPrimary10}; ++ mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary100 ++ : kColorRefPrimary0}; ++ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary0 ++ : kColorRefPrimary100}; + mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefSecondary10 + : kColorRefPrimary90}; + mixer[kColorSysOnBaseTonalContainer] = {dark_mode ? kColorRefSecondary90 +@@ -220,14 +222,13 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + : kColorRefPrimary90}; + + // Chrome surfaces. +- mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral25 : kColorRefNeutral100}; +- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral15 +- : kColorSysSurface4}; ++ mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral10 : kColorRefNeutral100}; ++ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral25 : kColorSysSurface4}; + mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefNeutral25 + : kColorRefNeutral100}; + +- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 +- : kColorRefPrimary90}; ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 ++ : kColorRefNeutral90}; + mixer[kColorSysHeaderInactive] = { + dark_mode + ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) +diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h +index cd70752a23e34..6725f520d89c2 100644 +--- a/ui/views/controls/menu/menu_item_view.h ++++ b/ui/views/controls/menu/menu_item_view.h +@@ -186,6 +186,10 @@ class VIEWS_EXPORT MenuItemView : public View, public LayoutDelegate { + + std::optional GetSelectedColorId() { return selected_color_id_; } + ++ void SetForegroundColorId(std::optional foreground_color_id) { ++ foreground_color_id_ = foreground_color_id; ++ } ++ + void SetHighlightWhenSelectedWithChildViews( + bool highlight_when_selected_with_child_views) { + highlight_when_selected_with_child_views_ = +@@ -596,10 +600,6 @@ class VIEWS_EXPORT MenuItemView : public View, public LayoutDelegate { + // Calculates the X coordinate of the icon. + int CalculateIconX(const ImageView* icon_view) const; + +- void SetForegroundColorId(std::optional foreground_color_id) { +- foreground_color_id_ = foreground_color_id; +- } +- + // Returns the corresponding margin from the `MenuConfig` if + // `vertical_margin_` is not set. + int GetVerticalMargin() const; +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.css b/ui/webui/resources/cr_components/searchbox/searchbox.css +index 34e70f33711a1..dc4fdb93e0fa3 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox.css +@@ -299,7 +299,7 @@ cr-searchbox-icon { + + :host([use-webkit-search-icons_][compose-button-enabled]) #voiceSearchButton, + :host([use-webkit-search-icons_][compose-button-enabled]) #lensSearchButton { +- background-color: #1F1F1F; ++ background-color: var(--color-searchbox-lens-voice-icon-background); + } + + :host([compose-button-enabled][searchbox-lens-search-enabled_]) { +diff --git a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts +index 6c77613866851..8c2a9b66df274 100644 +--- a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts ++++ b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts +@@ -29,26 +29,26 @@ export const DARK_DEFAULT_COLOR: Color = { + }; + + export const LIGHT_BASELINE_BLUE_COLOR: Color = { +- background: {value: 0xff0b57d0}, +- foreground: {value: 0xffd3e3fd}, +- base: {value: 0xffc7c7c7}, ++ background: {value: 0xff000000}, ++ foreground: {value: 0xffffffff}, ++ base: {value: 0xff606060}, + }; + + export const DARK_BASELINE_BLUE_COLOR: Color = { +- background: {value: 0xffa8c7fa}, +- foreground: {value: 0xff0842a0}, ++ background: {value: 0xffffffff}, ++ foreground: {value: 0xff000000}, + base: {value: 0xff757575}, + }; + + export const LIGHT_BASELINE_GREY_COLOR: Color = { +- background: {value: 0xff0b57d0}, +- foreground: {value: 0xffe3e3e3}, +- base: {value: 0xffc7c7c7}, ++ background: {value: 0xff000000}, ++ foreground: {value: 0xffffffff}, ++ base: {value: 0xff606060}, + }; + + export const DARK_BASELINE_GREY_COLOR: Color = { +- background: {value: 0xffa8c7fa}, +- foreground: {value: 0xff474747}, ++ background: {value: 0xffffffff}, ++ foreground: {value: 0xff000000}, + base: {value: 0xff757575}, + }; + From 35cb39a93de433b3907f696fa8dcc7d47b8bdb61 Mon Sep 17 00:00:00 2001 From: User Date: Tue, 6 Jan 2026 19:06:10 +0530 Subject: [PATCH 2/3] branding and script changes --- .../100_percent/product_logo_16.png | Bin 0 -> 1274 bytes .../100_percent/product_logo_16_root.png | Bin 0 -> 441 bytes .../100_percent/product_logo_16_white.png | Bin 0 -> 1285 bytes .../100_percent/product_logo_32.png | Bin 0 -> 1471 bytes .../100_percent/product_logo_32_white.png | Bin 0 -> 1498 bytes .../100_percent/product_logo_name_22.png | Bin 0 -> 2655 bytes .../product_logo_name_22_white.png | Bin 0 -> 2926 bytes .../200_percent/product_logo_16.png | Bin 0 -> 1274 bytes .../200_percent/product_logo_16_white.png | Bin 0 -> 1285 bytes .../200_percent/product_logo_32.png | Bin 0 -> 1471 bytes .../200_percent/product_logo_32_white.png | Bin 0 -> 1498 bytes .../200_percent/product_logo_name_22.png | Bin 0 -> 3759 bytes .../product_logo_name_22_white.png | Bin 0 -> 3924 bytes branding_assets/common/favicon_ntp_100.png | Bin 0 -> 1285 bytes branding_assets/common/favicon_ntp_200.png | Bin 0 -> 1498 bytes branding_assets/mac/app-temp.icns | Bin 0 -> 85977 bytes branding_assets/mac/app.icns | Bin 0 -> 12076 bytes branding_assets/ntp_icons/black_logo.svg | 4 + .../ntp_icons/openbrowser_logo_black.png | Bin 0 -> 4770 bytes .../ntp_icons/openbrowser_logo_white.png | Bin 0 -> 4538 bytes branding_assets/product_logo_128.png | Bin 0 -> 2200 bytes branding_assets/product_logo_16.png | Bin 0 -> 1274 bytes branding_assets/product_logo_22_mono.png | Bin 0 -> 1273 bytes branding_assets/product_logo_24.png | Bin 0 -> 1368 bytes branding_assets/product_logo_256.png | Bin 0 -> 3630 bytes branding_assets/product_logo_48.png | Bin 0 -> 1563 bytes branding_assets/product_logo_64.png | Bin 0 -> 1598 bytes .../side_panel_icons/mini_new_tab_page.svg | 77 + branding_assets/svg/product_logo.svg | 4 + .../patches/branding/branding_and_theme.patch | 3613 ++++++++++++++++ .../branding/branding_and_theme.patch.backup | 3678 +++++++++++++++++ chromium/patches/branding_url_changes.patch | 525 +++ chromium/patches/settings_ui_changes.patch | 895 ++++ .../patches/ui/theme_and_ui_changes.patch | 1250 ++++++ chromium/scripts/apply_patches.sh | 165 + scripts/apply_branding_assets.sh | 105 + scripts/apply_patches.sh | 100 + 37 files changed, 10416 insertions(+) create mode 100644 branding_assets/100_percent/product_logo_16.png create mode 100644 branding_assets/100_percent/product_logo_16_root.png create mode 100644 branding_assets/100_percent/product_logo_16_white.png create mode 100644 branding_assets/100_percent/product_logo_32.png create mode 100644 branding_assets/100_percent/product_logo_32_white.png create mode 100644 branding_assets/100_percent/product_logo_name_22.png create mode 100644 branding_assets/100_percent/product_logo_name_22_white.png create mode 100644 branding_assets/200_percent/product_logo_16.png create mode 100644 branding_assets/200_percent/product_logo_16_white.png create mode 100644 branding_assets/200_percent/product_logo_32.png create mode 100644 branding_assets/200_percent/product_logo_32_white.png create mode 100644 branding_assets/200_percent/product_logo_name_22.png create mode 100644 branding_assets/200_percent/product_logo_name_22_white.png create mode 100644 branding_assets/common/favicon_ntp_100.png create mode 100644 branding_assets/common/favicon_ntp_200.png create mode 100644 branding_assets/mac/app-temp.icns create mode 100644 branding_assets/mac/app.icns create mode 100644 branding_assets/ntp_icons/black_logo.svg create mode 100644 branding_assets/ntp_icons/openbrowser_logo_black.png create mode 100644 branding_assets/ntp_icons/openbrowser_logo_white.png create mode 100644 branding_assets/product_logo_128.png create mode 100644 branding_assets/product_logo_16.png create mode 100644 branding_assets/product_logo_22_mono.png create mode 100644 branding_assets/product_logo_24.png create mode 100644 branding_assets/product_logo_256.png create mode 100644 branding_assets/product_logo_48.png create mode 100644 branding_assets/product_logo_64.png create mode 100644 branding_assets/side_panel_icons/mini_new_tab_page.svg create mode 100644 branding_assets/svg/product_logo.svg create mode 100644 chromium/patches/branding/branding_and_theme.patch create mode 100644 chromium/patches/branding/branding_and_theme.patch.backup create mode 100644 chromium/patches/branding_url_changes.patch create mode 100644 chromium/patches/settings_ui_changes.patch create mode 100644 chromium/patches/ui/theme_and_ui_changes.patch create mode 100755 chromium/scripts/apply_patches.sh create mode 100755 scripts/apply_branding_assets.sh create mode 100755 scripts/apply_patches.sh diff --git a/branding_assets/100_percent/product_logo_16.png b/branding_assets/100_percent/product_logo_16.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a9634b7a797763d834fcc53c7e16bbc6bacfbf GIT binary patch literal 1274 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?VxrD>h#WBP}us6t>?~nnHFOyP0LW}f)L%b3@7{n8j z(jPMM+-cJ`FgTz%VaAQf2@@QgnzSBTW_d})gm|z2`26P9#~vT28eX|~{m*J!fxFCV zDY6MSx-6QnGqf!7SIb`?Vi7+t_`6p@ka+Y1u^%2+4~S$;I(U-L&&zM?HRrYqZSN-) z`dQSwohV+j^~?4MF7ap0smcNBD#8g26YerbIXLcM65?qJ@Y3xu-0b9*(h}X_bgraz zN5l6**?`@7ESgW*Vr7hrn)0Sycxe>*F?xY)zl0l8{8rtDA1PcL^zvGyW@JB*O1;3g zYodPv>x-o4h8xfDZGR9KCTaNTIlu0k1lAyXrD-$ES%SFg7H^Bqp00i_ I>zopr05XMrEC2ui literal 0 HcmV?d00001 diff --git a/branding_assets/100_percent/product_logo_16_root.png b/branding_assets/100_percent/product_logo_16_root.png new file mode 100644 index 0000000000000000000000000000000000000000..0823576ddadf204449377e7c5f26450cf6c81a1e GIT binary patch literal 441 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|DpDgn(|mmy zw18|51{Ovs23C*~Ahu(ahO^xmH5iz|;!F$-?U@WLP&Ix)8UzjiF-Q-DW?sMuRSgtd zzywz4nJ$hLzpWB=2SsX)P7o-U3d7J^rU4EdN81#I|F z-jv8S+4zy&?tuM`+c$m+)Sj|Ee96mte?oH7La{O}rgKsr)0oePsn0a9KJ)HitIqFg z6Cv{%ho#kOHhoL*T*POcbBq5@i1h4G=C5Z>^*7FQbdry0DA(GT*xkU!u5+V#S@7DK z->0n<{^6t7G9zPcy1}h;OB5MjvDvKMs=Q?R8fB>on|<|oyADYNdublOQ0Fmay|p8E zFZ3BLDyZ literal 0 HcmV?d00001 diff --git a/branding_assets/100_percent/product_logo_16_white.png b/branding_assets/100_percent/product_logo_16_white.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce13a8cadaf39315d4d92471e7b838486c11c85 GIT binary patch literal 1285 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?VxkT90#WBP}us7%+*C7L*+~+G!6|nQqJKB8z!O_j- z{|`2szi-wMZ)#h;%i@jrAKod)wk+jLXA&*DkkGT`>Sz1SI?^** z*iJ0Hu=$xx!u~J=)5>|5v)9$w&6xUe?SU47t{%6?7Ja{G%|EnlO%&^1-U$z<9Gxj< z5PV2+vJW5T?BE|KVmQ&$I1IiS9_W4$ADPh@N8;~U{0{@N@II=odqqUkPosKrO=KTS#b X2JzD@EDmqr1Z8edS3j3^P6NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg(UKbBnda-upao=eFt9QT zF)#yJj6lf1D8&FW4aj2fVw8rngBUfSYM2-p+A|qgplYIkGzc63VvrsP&AfmSVd4TN zxN3z3%m_A6HN)3v84^(v;p=0SoS&uf-VSw#k=7U$=bf}CY%XlY~vwgN>I z;XsHEgoe<(%o0187BpdWT@eU*BzurW(RKJ2Wu^jy65=wbyO70@)PwwI6_8nxniJuY znVXtd4DyYcsez3?RvC1i&iOg{MZpD$$*FdRP%TJ8=&Hf?MB=muNd~IZMjsU4NbwIz zTwqaP>aydq(TAs0JFdIRjhleEG#WBL)I@KX5K|^jN96ZLvd$$d!^i zebpBZFj_E}vPW=qRtVJ2}gp91=>NFBKS=9ED5&3E}dHv)YfWZo*SR1HYb{gwk10= zI&*I?y2Yg1$RL%lx;3~kROD#yk)EO#_VTM{R_ZbqpSh)f`jf=D$n_6qB;-G}xYn(9 zOrYS2cDcN>gQ`*GE#It);EouUz`_hS;oID>MWr{Q9a9f=D zHj$h0>ZDyk7rQ2`d->g>Y?U|L!~-V-YojwbFL=#mp0Z)D*>v3xR)x&p^f`T$w*Bg@ zzA=f-BO`00srSm7OYs)MLDL0~7T;(Ty0BH+cVENS`Oo(+_lS&Gp}MgGR4jSA`njxg HN@xNA+^XNC literal 0 HcmV?d00001 diff --git a/branding_assets/100_percent/product_logo_32_white.png b/branding_assets/100_percent/product_logo_32_white.png new file mode 100644 index 0000000000000000000000000000000000000000..6286728c00000fb93d5374dd5af52938ca48c857 GIT binary patch literal 1498 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg(UKbBnda-upao=eFt9QT zF)#yJj6lf1D8&FW4aj2fVw8rngBUfSYM2-p+A|qgplYIkGzc63VvrsP&AfmSVd4TN zxN3z3%m_A6HN)3v84^(v;p=0SoS&uf-VSw#k=7U$=bf}CY%XlY~vwgN>I z;XsHEgoe<(%o0187BpdWT@eU*BzurW(RKJ2Wu^jy65=wbyO70@)PwwI6_8nxniJuY znVXtd4DyYcsez3?RvC1i&iOg{MZpD$$*FdRP%TJ8=&Hf?MB=muNd~IZMjsU4NbwIz zTwqaP>aydq(TAs0JFdIRjhleEn;I{qrG0vK_RG@TEsJ~Cy;joU zH%y;p`6QQpL%&9s6ss5KZ$>6dvEnm}?@4@nCS7n{;lrYYw_cqW{$;J2G2yyY!bZLf zov^+zevX>+8)8|Qp3AiVE@#@t*7jmjmH3PjQC^NJ@ubgU8cGZsTrZoLdrsQpxhXtU zG&S;D$Bp9nJsk`Vw|1?Izid+bol&d)_O_BIdk)`LYHcXfAAFw}&^v4H>JG zS8ScaFgL!e&E2EpsFte1q|+~jw$3l}ny)Qrdcx`D_JCiqZ`MTpT9G&>fa(4Op#+OU z8TkVhCuIy2cAkE-MKaV><*7P31P-ilyWxbVpE5079YpU{sz zNfU%3o>kua?-qDzlg|7PxjPQLo;jDvi|4oPx^xk1GZ&TsUR6UOQP+>0(!S3f%J7E=Bu6=sjyABj>5jp$vQqME9JXfV7eYQ5&+5e>Q$XPRg%`bej z!Eo}F13aOz8}BmmL@#Y*_*%pf&hGMjx^t%v&+Vm*zs^YI+X`;c>8L%#>lR>D`b5Nd l^24>Vt}OEuU;LZ?SA23qT87*M7b{SS<>~6@vd$@?2>_fj?)?A& literal 0 HcmV?d00001 diff --git a/branding_assets/100_percent/product_logo_name_22.png b/branding_assets/100_percent/product_logo_name_22.png new file mode 100644 index 0000000000000000000000000000000000000000..b7fe29c00d79d7b8d7dc8e9717327d54acbd9b0a GIT binary patch literal 2655 zcmZ`*2{@E%8~(OeA$JSVmoGfDurkELK7)!}grv{a>6UM3N zNQv+lr!0-gPQ=B@nk7rwV^sbbocO!W|9;o|J?&XH%j-fkfqYqmR%+!vE3pBNIdRBL~`3aCibrdz-S$^dovR&*_~! z+)dj_v&*qfM8dhpz3ce5?$)N2bGcB$Nci`QiV~)cmi`6+0whaQw1Y4IZ0hL-M@N~+ zjmEA(W{v4V&q zlS=lO^?-(mrK47eD|w%cJ{L9xhkvX)R-9isROvHY)|36#Ej)+X-{;a9d;AcOzrT+P zS|8DY`6_7U5~y%MGE*xh3*Z}_KnC?08-j9Syk+xc?G@jNV)%fUo=1Fl6 zT5IBPtA?Q8uS3$5<}>@&G0uBsM^7nFznKv1E%LXMkHFv0>0(XTP6_rOR`I9n6_%{AH)ixxvX!tHO;33{00@y+5>Iz9-$;>Q) zdNBlp6q&Z+Kk075CsNk0lPLEyxHLA%I`3Pha8B{Pmc(|)DOGdVu&%OXeb2=YBwni~ZTT_BH zvsQU(NqJd`NvEbktwBw(qxGtHsRuPSUban_hVJQnQK23_;^~?#6O+v@ytmIiMH^zZ zY+n#jtJ*uPI2W0Gf={{UL1SO@Udy`h&f~A%JLTR0$!iG~=yV^tpT3m0@K-1LE3GM1 zmUs1q6{62Rp{bhHE@C`B^NXYF!gRy&*-PScb>JwBW@AsP9zE#lt3*jb+jU|-QiK$p zUwv&*{N2sZl6yp}mg@nd!%g7hYPL zZjf(#E_urv-TQ_5AMsA+dNLKL9hCoLaBwiP=N6uIsw_)wRI^ti7KMQJoqKRHveYfd zUUp(Ery}_3TCN=XCGvuxdhuI&2VIRY+pp9YrqP**E?yyKlcQw?tQXGJ+B|p4cx~YT zBMwQT7ue1s*}omtaj&PGnLeMY?%m>WweD=c0I9G(TxI59fN1~EC;l9|GlMAU1wKq8 zP;le)*vuhhRapWfe|5ZBFE!A@`-y&e>Fmfe`7>=}L+s$%J)ijGrD{sPd8vrCKGda1 z5g{q57%#rFO5{bO{i<(c>xxh-pP~A=y7gX0{%j8Oi>zpL%VVCDD0sU_wLQ4zxq>TW zg;cGT#;2M~4~2vXiPy?9_r(lT?p!vVnee>Y601RGi4e@2V#qvw3T2v0|1rM)b&I?V(0ZEkaXuE5#CK zA|XQxa}K^>&^4O_j&gj}F8fyaSc>SAqo-WlDUO64T>;k7F>#mlgL0W2#D&6^nGcAw<`LZ~{^o109?U z8#T4;R~;Yinj^k-Uu7*m6>qHVV5PAizKVc^Xa>FN(6*~`cr20WDVLFZjm0)+nf!HC zH*@w7TQvL*s@AQ$zMuqBBqgu-Vh!{rV^zB8D`|KMYnV2CGNaC+Dy3Apo%`M2@ZtN$FCk$iyT1zh4wsg#Z8m literal 0 HcmV?d00001 diff --git a/branding_assets/100_percent/product_logo_name_22_white.png b/branding_assets/100_percent/product_logo_name_22_white.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6a1238beb5d52192ea1ae75d745bf51865dba3 GIT binary patch literal 2926 zcmZ`*dpy(YAOA9POOm2SHCrVe?BbHkHslgcB9f7^nPF`V+Zws#Qbdc~iVm5VR3ua! zI>}uw3FSzgIXI@padg~rm$Su*U$67~?)B{RdETG*`*V4|&mZ47`{PGtrNPnw0LWTf znL7w9L9i4hHwpebRVRNF7%^{CTT=jdlqj=A5EtwrL@Nhd0Jv}f03t2{z=8mZ7zO|) z0s#KR1At*V04Vuq{&E5>2wWoJti5b)fkOgc5)c>J27m;fh~Ni^fB|7Pfd|-#D1Y-E zL=LWTL;)a{42Z39Tm@G6)CiVPvuZ&ck@bum(Qj-52lUNX6tDri&(-<@Bjs=9LI;4| zvBD*i_+f$s0HQC+Cvgm%?J+|l%~y-yN%J6S1^N05RRB83P~iHK7z9X=FV&B37=(d- zWf%&4Aq0T;4>6+!k|26o2rUE@D-D4_(1D&_h7RVIYjVL31NC7r{0-r7 z7K^3D($=B{dc%;N(YUVE>hT2Y;`^t;aXi*@%9xunQ!U1V_2r*;-#4 zu?>9Te1`VqAQBa4PWC1F(S_6KYa`I`|BQUEG^0^zfsXzJA_Sw)>nkd_Tv%x|{M$vvN;7z+F#sSDW^HbI(nowOoy@-NxV_0+ zSNj<9#yMsu$5HGNTk}J7nW~kILWbnFePzcammybtz;St@C3p8y^Gw0+`?jgxC_Vp3 z-0?@_)Kiynu4blxfn<}Uw0z?(m z#qUdc$+tF)VD^KJJVAi6n1@NM)NS=Vm%xuyszN!>q5MemmBecCbz} z$jyGRJGw|AQ|{3I8RoE-s7wu#Gt66{MJm@so6LKN%4xeUE${jy_OeD{;6#b$!Q?4F z(7ossQ)GMju%EbdBfyyn`?*WlDmM$*4d#+e>d&ZFuvR?cNcVoFnb&?|+?UaXl$WPW%GG;lBdvk5hZ7!GV-mvFP;opn+=*^yo_huxvCd*Vwp_?Het7WEH zysn6z+A$7$x?INCijB>|UQ3=2mrVfVKc1b_HtGC`fchL@Q*GGD5E8`?vv?~mFb8*m$PJTi{LfQ7*H~sznd$zEDyK|OWobb5NH9vH7 z|E-ssblz)EOq{z94b6Rah9WX4z0`|Knm(N{HjNnIf>v<;80l2oP zZ8M8IwO(B^{=%z554XdKUwS^Y+w$l7(KKiPrPAX z4ZrB5mr!08c>Tr1)|-*RH6eYYsKA(4R@s!u%gJvtAGGUg9y#Oa=t!hcDBfmf^;>eM z3c{Z>xyvSYBhu_rq?`Wo-FpPPfV#o{ykk6HU(!vg_3e1v6j>d%TxO?Q2{$JZZ#;}% zpyfUeYjmP+eO9UAUEITI8KTy z0$%s$S~UcZ*6ts08CZHyyEliB8P-w->SdP@+-9>m)10fLG}}KgYR~$fhrpVRiVN^$ zd2oVA#@b z$hE}uGnlGzCD8J(o3nROad!l zL$`JBe5U?!T7BX3e!cex!;6Z*9^q`TGbnp=zcM`9b^E9yuV+%Oy7_qJt#++jt6kmR~h!9q}+k zJjnKZl+*j1lB7pAIVv!{5vQ)mI@$1RDiVf#SagSHjPHX~UL7!1RqG8t#49vw-*%)Y z3cUkItu8oLa7wGF}knY%gSj#Q!uG=@~ZykN5-A#)+aC~5eDOxQ;&~x6Nw)Iza;a8-!#c}hZBlxI) E0DvsgP5=M^ literal 0 HcmV?d00001 diff --git a/branding_assets/200_percent/product_logo_16.png b/branding_assets/200_percent/product_logo_16.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a9634b7a797763d834fcc53c7e16bbc6bacfbf GIT binary patch literal 1274 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?VxrD>h#WBP}us6t>?~nnHFOyP0LW}f)L%b3@7{n8j z(jPMM+-cJ`FgTz%VaAQf2@@QgnzSBTW_d})gm|z2`26P9#~vT28eX|~{m*J!fxFCV zDY6MSx-6QnGqf!7SIb`?Vi7+t_`6p@ka+Y1u^%2+4~S$;I(U-L&&zM?HRrYqZSN-) z`dQSwohV+j^~?4MF7ap0smcNBD#8g26YerbIXLcM65?qJ@Y3xu-0b9*(h}X_bgraz zN5l6**?`@7ESgW*Vr7hrn)0Sycxe>*F?xY)zl0l8{8rtDA1PcL^zvGyW@JB*O1;3g zYodPv>x-o4h8xfDZGR9KCTaNTIlu0k1lAyXrD-$ES%SFg7H^Bqp00i_ I>zopr05XMrEC2ui literal 0 HcmV?d00001 diff --git a/branding_assets/200_percent/product_logo_16_white.png b/branding_assets/200_percent/product_logo_16_white.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce13a8cadaf39315d4d92471e7b838486c11c85 GIT binary patch literal 1285 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?VxkT90#WBP}us7%+*C7L*+~+G!6|nQqJKB8z!O_j- z{|`2szi-wMZ)#h;%i@jrAKod)wk+jLXA&*DkkGT`>Sz1SI?^** z*iJ0Hu=$xx!u~J=)5>|5v)9$w&6xUe?SU47t{%6?7Ja{G%|EnlO%&^1-U$z<9Gxj< z5PV2+vJW5T?BE|KVmQ&$I1IiS9_W4$ADPh@N8;~U{0{@N@II=odqqUkPosKrO=KTS#b X2JzD@EDmqr1Z8edS3j3^P6NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg(UKbBnda-upao=eFt9QT zF)#yJj6lf1D8&FW4aj2fVw8rngBUfSYM2-p+A|qgplYIkGzc63VvrsP&AfmSVd4TN zxN3z3%m_A6HN)3v84^(v;p=0SoS&uf-VSw#k=7U$=bf}CY%XlY~vwgN>I z;XsHEgoe<(%o0187BpdWT@eU*BzurW(RKJ2Wu^jy65=wbyO70@)PwwI6_8nxniJuY znVXtd4DyYcsez3?RvC1i&iOg{MZpD$$*FdRP%TJ8=&Hf?MB=muNd~IZMjsU4NbwIz zTwqaP>aydq(TAs0JFdIRjhleEG#WBL)I@KX5K|^jN96ZLvd$$d!^i zebpBZFj_E}vPW=qRtVJ2}gp91=>NFBKS=9ED5&3E}dHv)YfWZo*SR1HYb{gwk10= zI&*I?y2Yg1$RL%lx;3~kROD#yk)EO#_VTM{R_ZbqpSh)f`jf=D$n_6qB;-G}xYn(9 zOrYS2cDcN>gQ`*GE#It);EouUz`_hS;oID>MWr{Q9a9f=D zHj$h0>ZDyk7rQ2`d->g>Y?U|L!~-V-YojwbFL=#mp0Z)D*>v3xR)x&p^f`T$w*Bg@ zzA=f-BO`00srSm7OYs)MLDL0~7T;(Ty0BH+cVENS`Oo(+_lS&Gp}MgGR4jSA`njxg HN@xNA+^XNC literal 0 HcmV?d00001 diff --git a/branding_assets/200_percent/product_logo_32_white.png b/branding_assets/200_percent/product_logo_32_white.png new file mode 100644 index 0000000000000000000000000000000000000000..6286728c00000fb93d5374dd5af52938ca48c857 GIT binary patch literal 1498 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg(UKbBnda-upao=eFt9QT zF)#yJj6lf1D8&FW4aj2fVw8rngBUfSYM2-p+A|qgplYIkGzc63VvrsP&AfmSVd4TN zxN3z3%m_A6HN)3v84^(v;p=0SoS&uf-VSw#k=7U$=bf}CY%XlY~vwgN>I z;XsHEgoe<(%o0187BpdWT@eU*BzurW(RKJ2Wu^jy65=wbyO70@)PwwI6_8nxniJuY znVXtd4DyYcsez3?RvC1i&iOg{MZpD$$*FdRP%TJ8=&Hf?MB=muNd~IZMjsU4NbwIz zTwqaP>aydq(TAs0JFdIRjhleEn;I{qrG0vK_RG@TEsJ~Cy;joU zH%y;p`6QQpL%&9s6ss5KZ$>6dvEnm}?@4@nCS7n{;lrYYw_cqW{$;J2G2yyY!bZLf zov^+zevX>+8)8|Qp3AiVE@#@t*7jmjmH3PjQC^NJ@ubgU8cGZsTrZoLdrsQpxhXtU zG&S;D$Bp9nJsk`Vw|1?Izid+bol&d)_O_BIdk)`LYHcXfAAFw}&^v4H>JG zS8ScaFgL!e&E2EpsFte1q|+~jw$3l}ny)Qrdcx`D_JCiqZ`MTpT9G&>fa(4Op#+OU z8TkVhCuIy2cAkE-MKaV><*7P31P-ilyWxbVpE5079YpU{sz zNfU%3o>kua?-qDzlg|7PxjPQLo;jDvi|4oPx^xk1GZ&TsUR6UOQP+>0(!S3f%J7E=Bu6=sjyABj>5jp$vQqME9JXfV7eYQ5&+5e>Q$XPRg%`bej z!Eo}F13aOz8}BmmL@#Y*_*%pf&hGMjx^t%v&+Vm*zs^YI+X`;c>8L%#>lR>D`b5Nd l^24>Vt}OEuU;LZ?SA23qT87*M7b{SS<>~6@vd$@?2>_fj?)?A& literal 0 HcmV?d00001 diff --git a/branding_assets/200_percent/product_logo_name_22.png b/branding_assets/200_percent/product_logo_name_22.png new file mode 100644 index 0000000000000000000000000000000000000000..8e4c9f9ee9560c443b48e0d9267dc6fc05fd10af GIT binary patch literal 3759 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 LS->j|-Om3TieGrn literal 0 HcmV?d00001 diff --git a/branding_assets/200_percent/product_logo_name_22_white.png b/branding_assets/200_percent/product_logo_name_22_white.png new file mode 100644 index 0000000000000000000000000000000000000000..87cd9fee473bd5a567d0bf6a0bd47139ecdd2fc5 GIT binary patch literal 3924 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 literal 0 HcmV?d00001 diff --git a/branding_assets/common/favicon_ntp_100.png b/branding_assets/common/favicon_ntp_100.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce13a8cadaf39315d4d92471e7b838486c11c85 GIT binary patch literal 1285 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?VxkT90#WBP}us7%+*C7L*+~+G!6|nQqJKB8z!O_j- z{|`2szi-wMZ)#h;%i@jrAKod)wk+jLXA&*DkkGT`>Sz1SI?^** z*iJ0Hu=$xx!u~J=)5>|5v)9$w&6xUe?SU47t{%6?7Ja{G%|EnlO%&^1-U$z<9Gxj< z5PV2+vJW5T?BE|KVmQ&$I1IiS9_W4$ADPh@N8;~U{0{@N@II=odqqUkPosKrO=KTS#b X2JzD@EDmqr1Z8edS3j3^P6NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg(UKbBnda-upao=eFt9QT zF)#yJj6lf1D8&FW4aj2fVw8rngBUfSYM2-p+A|qgplYIkGzc63VvrsP&AfmSVd4TN zxN3z3%m_A6HN)3v84^(v;p=0SoS&uf-VSw#k=7U$=bf}CY%XlY~vwgN>I z;XsHEgoe<(%o0187BpdWT@eU*BzurW(RKJ2Wu^jy65=wbyO70@)PwwI6_8nxniJuY znVXtd4DyYcsez3?RvC1i&iOg{MZpD$$*FdRP%TJ8=&Hf?MB=muNd~IZMjsU4NbwIz zTwqaP>aydq(TAs0JFdIRjhleEn;I{qrG0vK_RG@TEsJ~Cy;joU zH%y;p`6QQpL%&9s6ss5KZ$>6dvEnm}?@4@nCS7n{;lrYYw_cqW{$;J2G2yyY!bZLf zov^+zevX>+8)8|Qp3AiVE@#@t*7jmjmH3PjQC^NJ@ubgU8cGZsTrZoLdrsQpxhXtU zG&S;D$Bp9nJsk`Vw|1?Izid+bol&d)_O_BIdk)`LYHcXfAAFw}&^v4H>JG zS8ScaFgL!e&E2EpsFte1q|+~jw$3l}ny)Qrdcx`D_JCiqZ`MTpT9G&>fa(4Op#+OU z8TkVhCuIy2cAkE-MKaV><*7P31P-ilyWxbVpE5079YpU{sz zNfU%3o>kua?-qDzlg|7PxjPQLo;jDvi|4oPx^xk1GZ&TsUR6UOQP+>0(!S3f%J7E=Bu6=sjyABj>5jp$vQqME9JXfV7eYQ5&+5e>Q$XPRg%`bej z!Eo}F13aOz8}BmmL@#Y*_*%pf&hGMjx^t%v&+Vm*zs^YI+X`;c>8L%#>lR>D`b5Nd l^24>Vt}OEuU;LZ?SA23qT87*M7b{SS<>~6@vd$@?2>_fj?)?A& literal 0 HcmV?d00001 diff --git a/branding_assets/mac/app-temp.icns b/branding_assets/mac/app-temp.icns new file mode 100644 index 0000000000000000000000000000000000000000..97072c8c1157d2d180f4ff592ecafe37333fb6b9 GIT binary patch literal 85977 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 literal 0 HcmV?d00001 diff --git a/branding_assets/mac/app.icns b/branding_assets/mac/app.icns new file mode 100644 index 0000000000000000000000000000000000000000..2ec93f208bae45984a2f147bfa487863190e64b5 GIT binary patch literal 12076 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 + + + diff --git a/branding_assets/ntp_icons/openbrowser_logo_black.png b/branding_assets/ntp_icons/openbrowser_logo_black.png new file mode 100644 index 0000000000000000000000000000000000000000..95cbd5da9796c150ae300cb4abf593574e66bc5c GIT binary patch literal 4770 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 literal 0 HcmV?d00001 diff --git a/branding_assets/ntp_icons/openbrowser_logo_white.png b/branding_assets/ntp_icons/openbrowser_logo_white.png new file mode 100644 index 0000000000000000000000000000000000000000..4d76e00f886133bb31c6fd9ad594d8698717a47c GIT binary patch literal 4538 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 H=^XhV7;i__ literal 0 HcmV?d00001 diff --git a/branding_assets/product_logo_128.png b/branding_assets/product_logo_128.png new file mode 100644 index 0000000000000000000000000000000000000000..c901d2e6081a68b084c2681ab4e278714e002dba GIT binary patch literal 2200 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCjKy@t)48K6?UobF~8Za=tN?>5Hn!&&zUNC1@pbb!>B{jk`&DWPf3&`eRU}Y3y zUyEB#05-n z)eQ@n5p1AphWHvQT_D9-;1OBOz#!WW!i@b-Kc+G;FrCQ^i71Ki^|4CM&(%vz$xlkv ztH>0+>{umUo3Q%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)CuG zfu4bq9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)Btk zRH0j3nOBlnp_^B%3^4>|j!SBBa#3bMNoIbY0?6FNr2NtnTO}osMQ{LdXGvxn!lt}p zsJDO~)CbAv8|oS8W7C#ek%>baNCu(}>@SFQHXy^SB7;(k^K(i;&ayMKG_nC(fg*}< zAVdd3Lug)Ri5*M}nlQSq2!uS6J;TzE!&9mq*InhtO~8D+%+tj&q=ND7+`W0ifdZ|`?~|M+vwJiO2$?EaWpPcY z=n#3xTG6_Pnb)5s#KS~GRY)^q!i3Mwk7snYC~0qcUs{${_Pobm#k=qQxjV+sYc?t0 znEmF>hwRm|5}M1eU(?>6{&Ny@_tNLm_E*^|RIK;jtuT*!@$^7=X3d4AmA98>tbDf7 zrheNO+xdKt53G5;?eV(S|F89?e%0Atm|(z=^JMes1ip;>jBLW^dUItI7|iSrl_@f8 zxOkI8osR75^SCzzZd`Uc#pvffld}hJ-n@BrmbXIOy}Ng7%j@duBm#3X7*zhe1cK=o zGfet3?k$^jYg_H!ms@M&#s4ZhRF|yHx4-`O`kH8oUteD^@Vxc^^_SD(SI22)p@vQN zFT*KeFJ@-=d;b8(7Z>&i`c0iDq!u$bywPnbV`31TJl})q!E;@gbgb;RMb9_C4Lt%M{b4=asB@y;Q}DA?;8JFr0=|)jX|IJ;%^~_FDz4kaW-6X_)^5wFmFMSJ!61WN1PwS z1>ula>I`1Y7f*9CR5f}1WpT(lpY!|5 z*1gj+mO07A7?JD$F?4f(!|PZTj>+Yd7d^V#{XJ~I&7aj5>)9mkEqubo;qa*;`>|ld zEa#KgIqAq=%q;MYU-!<$?whjf-@pBI;W^V2vv=;fx8=H|mu+wV{%l>&6_c}0=gjxK z`0a3NnQmL$m)+X8&iDGnt=n7wPwK5dk-Q@Q@V(M^KBd>w)#}P*J*po(YRs{j$jQt` lR)@VSeZH=}k@#BX2YbN7tlMv1e#!*Zx1O$kF6*2UngCRsG(`Xa literal 0 HcmV?d00001 diff --git a/branding_assets/product_logo_16.png b/branding_assets/product_logo_16.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a9634b7a797763d834fcc53c7e16bbc6bacfbf GIT binary patch literal 1274 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?VxrD>h#WBP}us6t>?~nnHFOyP0LW}f)L%b3@7{n8j z(jPMM+-cJ`FgTz%VaAQf2@@QgnzSBTW_d})gm|z2`26P9#~vT28eX|~{m*J!fxFCV zDY6MSx-6QnGqf!7SIb`?Vi7+t_`6p@ka+Y1u^%2+4~S$;I(U-L&&zM?HRrYqZSN-) z`dQSwohV+j^~?4MF7ap0smcNBD#8g26YerbIXLcM65?qJ@Y3xu-0b9*(h}X_bgraz zN5l6**?`@7ESgW*Vr7hrn)0Sycxe>*F?xY)zl0l8{8rtDA1PcL^zvGyW@JB*O1;3g zYodPv>x-o4h8xfDZGR9KCTaNTIlu0k1lAyXrD-$ES%SFg7H^Bqp00i_ I>zopr05XMrEC2ui literal 0 HcmV?d00001 diff --git a/branding_assets/product_logo_22_mono.png b/branding_assets/product_logo_22_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..d7259c33706a9baa734b4bd0bf5edc6739e37d22 GIT binary patch literal 1273 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBC{d9b;hE;^%b*2hb1<+l zN-=;;U<6`2MrkXQ2>tmIipR1RclAn~SSCLx) z(#2p?VFhI7rj{fsROII56h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGMveo=5iVsfgTA=EA;A*gB_eNgNn#U>=FfJK36#g5BHAD-^)xa{{BxB%0bSVzn4eU~p^ zeNnyISgb7g7?^##%Ghr%VM zuT3txP!)1x>b*muq2`OXdbB0%vuoXODP=IP3(*mr zY9;$mR&rN_UkS>#Elu3Dzb*0SYnzPc;Y&4poj=`cbhABGutn(T7oqRQAGbBfoT+(L zbg{=xzx2(KEf*&-@KqZwpR+r;U#jV;O3nHY=k@%Bu5EXo{O9HT?<^15bQ(B{7X4oP y{%En@i`coTlgt}V+}rV}uF3Gi@hr8UyfuuHRo3xe>!(fxWo}PbKbLh*2~7abo}F0$ literal 0 HcmV?d00001 diff --git a/branding_assets/product_logo_24.png b/branding_assets/product_logo_24.png new file mode 100644 index 0000000000000000000000000000000000000000..d0d6d6cbbecb4207264b7263e9c2883ac1c04b98 GIT binary patch literal 1368 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nO75STeGsl~}fnFS@8`FRQ;a}$&DOG|8(lt3220mPjpnP~`{ z@`|C}0(wv%B%^PrXP}QwTWUon4s9SAh&HglAlBJ{46}+1N-fUMDFr#p&d}1x25be2 zD8hjd9S9Afd6^}4FfC}p=(-{h@<{d|i=ylBFUm{>1|`I0P{OWup&Isdijej#h6{sZKr}WLBlPy@6OYDN=K)r>*t7FG&M4%!@zIvCSP^M02-XHC>##{yfU`AwwI2Hf|stBM@haypXbORLF#*pX`0FD&>ov!bwWcBcMKtfI%O7c@iB;gQxI1cEyY)o4&4_kjo>-4;@xV(=k#o{k`o*Oxm2Pjm!nR-a>GO>Qa8RVxIh8r5%}?a1;0g87?e+;Q62|vY+a6Y zA}W|LAy%PNt1_svg8c&hMPn&`Wt}L{!I&VdBbEB#$CN4NsVv!qe^Q>w)~Spbtx^G7 z>8NbHuF1AZcxrt@snVcO$;8TZ1*xM}6Y#RHNbsAUsmxVsm0J6XCM8V~>^DxCWSWW| z%aicbJd-@*Op$_IW4OkwaJqsSBEgeM4QALp%_jh0h$6)yYYoWV8-C>Lp{~>A zbs{$}&dk_du4}wy+ZW2v-IkD*3Fsy{;>~ilq`KVyF**|`OaMVK9_uRB*#DFN;6AH8j9t&Gd~MF7 zbbI2!tBX&7ZHavQx{BS0R^4=`4;}A%Xzx4S{&{CkQqK7o3B1IF))(f#OV_idz;<*7 zcTWs~+-W!)hE+Lvo5=5{yVNhRfIda4Cu+l7iKTDm(CLuBo0mDo~bLfgaAndU5%fhY3&ya_1E-fuJ`c#b8Hq$E__gXuzRCp90K5QGw zKVQH=MrT^k&Y<{Nvc zd!;3oK-O-z3(b2mS8If_%Gn%+(4GyW3mx+*{&SJS-?y@kTAVtHSsoNUghV9_~JaLYwzB8pAu&XY?I5?`25dVv+i zn&I3RpE-wp3Ahnt9?SmiMy||4%Q> zx1GALcI_%^2|xK&{Ja_)>9Kf4T(M?FvhCi$fUehiY_^p#)X>n79ADGeaoJ|K+fOx+ z1tdw%JobkR-9kpLn_O&EfK7>#-e&WANi9G-BR+m+7C)k%DK2 zKcgR=xlLtn+pcGNSH5=PTGOp9uguF3eeH8SQESv{`&9O(nV=PDDL?I#pZCUF}6Zc`g53At=fI*10GY|Bv;qdZ?l0 p=a`GbWuaqVb7P-%)?v=WS>HU=Fy$>L;ZGd^k)aZC`AYfrUjPY24XOYD literal 0 HcmV?d00001 diff --git a/branding_assets/product_logo_48.png b/branding_assets/product_logo_48.png new file mode 100644 index 0000000000000000000000000000000000000000..b9c78d0e08a371994276fdc63bee93425ff91a4c GIT binary patch literal 1563 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLXi1ImO!M_+&;qhK7+4vF z7?^=9Mj&Khlwtsx24pdKF-pVPL5vzuHB1Z)?U@WLP&H9N8UzjiF-Q-DW?sOEFmVAB zT(!XhW&|6kn&HgRpfDiCS>O>_%)lTE^p|WqWB=2SsSFHEXEH+~N+NuHtdjF{^%7I^ zlT!66atlDZ7;Gx6fXv*~l0=1y+?>2(s|s5sunH?68zii+qySb@l5MLL;TxdfoL`ix zV5VoFXP{)qrJ$f-Q4fw@;;CqokB%_3GY znMUUV=51>%nK?SS3mEe*ioWL3NS$eBKW}N+ijz0|Y&tKu>h|6`v**m2*`9AK)^2y_ z=YQ2;#=GpSVC0EwH||^gvgi2tl~>8GJk>^F;`A&dBPP2B@d=(^TNwNOSKLtc+Iej$ z*KL7iOHw()$ zHZLlz>U!<4{HaO7HE;H7ubspDZ+S%>d(ALOXOhawy{kno9y0KG_W7rFS+?)BMxog= zwSQQLr`@_#!SzSo<;-)VpKZELC5CbjUBuEC?_bRHwTLsY(ZuSpc49b3#*dR{`x^F` zmFcWwE_!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVjk0Ai3H2+h2J5nlF>KRGtkGTEwv&Ohc=K5L>t&&5bJC}hFL`hr55Msl!BaPXJ~0;1GWN1 z6yZRK4upo#yv!0im=-i)bX^e$c_e#~MbUNm7iFdbgA(F0sJoEGkko_xXBCiHk(v|X zl9`*DR}AuvnW=$|K2{lYozD3=`9;A6iOH#UhEOd?Lg=c&_C(^e2T2C1(?%Z@-$?Nf zNnBu2VCu5tveAd9R6DM_%8i?V>DtHB#WAFU@oki~-(d%V-ee!4i!-%^Y=s&pP2($M zl{)9>?bvL=Alkmb;Sozm)3oRXDnfx1dhPd2)e!JX%YA?2O|wNujTAHn6_ru=$)Q)r*@`6yXmox`V^tXeBT((X{Igx>>$zh ze)36`b(SdKTsi-Fj*95@&IALAnB|#O zT%{|F-PTT2Ihm*1aBSvOhBcxht_!PgEeX1H+$Jpk6`w$axYMu6cahvk`veMd&FMJH=pTAn|`ecUR^8A8;%_k+y z8P^`(QNf!~`{9uil#D&IZfT?f*$RT6gBHW{~XWjRt|P;`D;EPLY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branding_assets/svg/product_logo.svg b/branding_assets/svg/product_logo.svg new file mode 100644 index 0000000..e10b921 --- /dev/null +++ b/branding_assets/svg/product_logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/chromium/patches/branding/branding_and_theme.patch b/chromium/patches/branding/branding_and_theme.patch new file mode 100644 index 0000000..aa7626b --- /dev/null +++ b/chromium/patches/branding/branding_and_theme.patch @@ -0,0 +1,3613 @@ +diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd +index 824563af91ce5..5aa88b8112b94 100644 +--- a/chrome/app/chromium_strings.grd ++++ b/chrome/app/chromium_strings.grd +@@ -278,7 +278,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + + + +- Chromium ++ OpenBrowser + + +- Chromium ++ OpenBrowser + + + + +- ++ + +- ++ + +- ++ + + +- Chromium is a web browser that runs webpages and applications with lightning speed. It's fast, stable, and easy to use. Browse the web more safely with malware and phishing protection built into Chromium. ++ OpenBrowser is a web browser that runs webpages and applications with lightning speed. It's fast, stable, and easy to use. Browse the web more safely with malware and phishing protection built into OpenBrowser. + + +- Welcome to Chromium; new browser window opened ++ Welcome to OpenBrowser; new browser window opened + + + + +- Welcome to Chromium ++ Welcome to OpenBrowser + + + + +- ChromiumOS ++ OpenBrowserOS + + +- ChromiumOS ++ OpenBrowserOS + + +- ChromiumOS ++ OpenBrowserOS + + +- +- Chromium Enterprise logo ++ ++ OpenBrowser Enterprise logo + + + +@@ -346,7 +346,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- Task Manager - Chromium ++ Task Manager - OpenBrowser + + + +@@ -380,12 +380,12 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + All tasks + + +- Help make Chromium better by sending crash reports and $1usage statistics to Google ++ Help make OpenBrowser better by sending crash reports and $1usage statistics to Google + + + This action will: + <br><br> +- • Reset some Chromium settings and Chromium shortcuts ++ • Reset some OpenBrowser settings and OpenBrowser shortcuts + <br> + • Disable extensions + <br> +@@ -403,7 +403,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- $1Google - Chromium ++ $1Google - OpenBrowser + + + +@@ -411,19 +411,19 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- Chromium - $1Google ++ OpenBrowser - $1Google + + + + + +- $1Google - Network Sign-in - Chromium ++ $1Google - Network Sign-in - OpenBrowser + + + + + +- Chromium - Network Sign-in - $1Google ++ OpenBrowser - Network Sign-in - $1Google + + + +@@ -442,18 +442,18 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- $1Google - Chromium ++ $1Google - OpenBrowser + + + + +- $1Google - Chromium Beta ++ $1Google - OpenBrowser Beta + + +- $1Google - Chromium Dev ++ $1Google - OpenBrowser Dev + + +- $1Google - Chromium Canary ++ $1Google - OpenBrowser Canary + + + +@@ -466,22 +466,22 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- The Chromium Authors ++ The OpenBrowser Authors + + +- Copyright {0,date,y}2016 The Chromium Authors. All rights reserved. ++ Copyright {0,date,y}2016 The OpenBrowser Authors. All rights reserved. + + + + +- +- ChromiumOS is made possible by additional <a target="_blank" href="$1">open source software</a>. ++ ++ OpenBrowserOS is made possible by additional <a target="_blank" href="$1">open source software</a>. + +- +- ChromiumOS is made possible by additional <a target="_blank" href="$1">open source software</a>, as is <a target="_blank" href="$2">Linux development environment</a>. ++ ++ OpenBrowserOS is made possible by additional <a target="_blank" href="$1">open source software</a>, as is <a target="_blank" href="$2">Linux development environment</a>. + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + + +@@ -492,108 +492,108 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + + + + +- To get future Chromium updates, you'll need macOS 12 or later. This computer is using macOS 11. ++ To get future OpenBrowser updates, you'll need macOS 12 or later. This computer is using macOS 11. + + + + +- Chromium may not function correctly because it is no longer supported on Windows XP or Windows Vista ++ OpenBrowser may not function correctly because it is no longer supported on Windows XP or Windows Vista + + + + +- To get future Chromium updates, you'll need Windows 10 or later. This computer is using Windows 7. ++ To get future OpenBrowser updates, you'll need Windows 10 or later. This computer is using Windows 7. + + + + +- To get future Chromium updates, you'll need Windows 10 or later. This computer is using Windows 8. ++ To get future OpenBrowser updates, you'll need Windows 10 or later. This computer is using Windows 8. + + + + +- To get future Chromium updates, you'll need Windows 10 or later. This computer is using Windows 8.1. ++ To get future OpenBrowser updates, you'll need Windows 10 or later. This computer is using Windows 8.1. + + + + +- Chromium may not function correctly because it is no longer supported on this Linux distribution ++ OpenBrowser may not function correctly because it is no longer supported on this Linux distribution + + + +- Chromium ++ OpenBrowser + + + + +- Chromium is unresponsive. Relaunch now? ++ OpenBrowser is unresponsive. Relaunch now? + + + + +- To send a number from here to your Android phone, sign in to Chromium on both devices. ++ To send a number from here to your Android phone, sign in to OpenBrowser on both devices. + + +- To send a number from $1www.google.com to your Android phone, sign in to Chromium on both devices. ++ To send a number from $1www.google.com to your Android phone, sign in to OpenBrowser on both devices. + + +- Make sure you are signed in to Chromium on your $1Pixel XL and then try sending again. ++ Make sure you are signed in to OpenBrowser on your $1Pixel XL and then try sending again. + + + + +- Please close all Chromium windows and try again. ++ Please close all OpenBrowser windows and try again. + + +- Are you sure you want to uninstall Chromium? ++ Are you sure you want to uninstall OpenBrowser? + +- +- Uninstall Chromium ++ ++ Uninstall OpenBrowser + + + +- Make Chromium the default browser ++ Make OpenBrowser the default browser + + + +- Let Chromium Run in the Background ++ Let OpenBrowser Run in the Background + + + + +- Let Chromium run in the background ++ Let OpenBrowser run in the background + + + + +- Disable Chromium Running in Background for Apps ++ Disable OpenBrowser Running in Background for Apps + + + + +- Disable Chromium running in background for apps ++ Disable OpenBrowser running in background for apps + + + +-Chromium cannot read and write to its data directory: ++OpenBrowser cannot read and write to its data directory: + + $1C:\Documents and Settings\devint\Local Settings\Application Data\Google\Chrome + + + +- Optional: Help improve ChromiumOS features and performance by automatically sending diagnostic and usage data to Google. ++ Optional: Help improve OpenBrowserOS features and performance by automatically sending diagnostic and usage data to Google. + + + +-Your profile can not be used because it is from a newer version of Chromium. ++Your profile can not be used because it is from a newer version of OpenBrowser. + +-Some features may be unavailable. Please specify a different profile directory or use a newer version of Chromium. ++Some features may be unavailable. Please specify a different profile directory or use a newer version of OpenBrowser. + + + Your preferences can not be read. +@@ -603,21 +603,21 @@ Some features may be unavailable and changes to preferences won't be saved. + + Your preferences file is corrupt or invalid. + +-Chromium is unable to recover your settings. ++OpenBrowser is unable to recover your settings. + + + + +- Open $1https://www.example-url.com/ in a new tab in Chromium. ++ Open $1https://www.example-url.com/ in a new tab in OpenBrowser. + + + + + +- Chromium lets you know if your passwords are ever compromised ++ OpenBrowser lets you know if your passwords are ever compromised + + +- Chromium ++ OpenBrowser + + + Password Manager +@@ -630,81 +630,81 @@ Chromium is unable to recover your settings. + + + +- Chromium is trying to $1show passwords ++ OpenBrowser is trying to $1show passwords + + + + +- Chromium is trying to show passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to show passwords. Type your Windows password to allow this. + + +- Chromium is trying to copy passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to copy passwords. Type your Windows password to allow this. + + +- Chromium is trying to edit passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to edit passwords. Type your Windows password to allow this. + + +- Chromium wants to export your passwords. Type your Windows password to allow this. ++ OpenBrowser wants to export your passwords. Type your Windows password to allow this. + + +- Chromium wants to delete your Password Manager data. Type your Windows password to allow this. ++ OpenBrowser wants to delete your Password Manager data. Type your Windows password to allow this. + + +- Chromium is trying to replace existing passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to replace existing passwords. Type your Windows password to allow this. + + +- This computer already has a more recent version of Chromium. If the software is not working, please uninstall Chromium and try again. ++ This computer already has a more recent version of OpenBrowser. If the software is not working, please uninstall OpenBrowser and try again. + + +- Installation failed due to unspecified error. If Chromium is currently running, please close it and try again. ++ Installation failed due to unspecified error. If OpenBrowser is currently running, please close it and try again. + + +- Can not install the same Chromium version that is currently running. Please close Chromium and try again. ++ Can not install the same OpenBrowser version that is currently running. Please close OpenBrowser and try again. + + +- Chromium requires Windows 10 or higher. ++ OpenBrowser requires Windows 10 or higher. + + +- An operating system error occurred during installation. Please download Chromium again. ++ An operating system error occurred during installation. Please download OpenBrowser again. + + +- Another operation on Chromium is in progress. Please try again later. ++ Another operation on OpenBrowser is in progress. Please try again later. + + + The installer couldn't create a temporary directory. Please check for free disk space and permission to install software. + + +- The installer failed to uncompress archive. Please download Chromium again. ++ The installer failed to uncompress archive. Please download OpenBrowser again. + + +- The installer archive is corrupted or invalid. Please download Chromium again. ++ The installer archive is corrupted or invalid. Please download OpenBrowser again. + + + You do not have appropriate rights for system-level install. Try running the installer again as Administrator. + + +- Chromium is already installed for all users on your computer. ++ OpenBrowser is already installed for all users on your computer. + + +- Provides elevated privileges for $1Chromium. ++ Provides elevated privileges for $1OpenBrowser. + + +- Provides system tracing services for $1Chromium. If this service is disabled, performance traces created by the browser will not include system-wide events such as context switch and ready thread events. ++ Provides system tracing services for $1OpenBrowser. If this service is disabled, performance traces created by the browser will not include system-wide events such as context switch and ready thread events. + + + + +- Import Passwords To Chromium ++ Import Passwords To OpenBrowser + + +- Export Passwords From Chromium ++ Export Passwords From OpenBrowser + + + + +- ++ + Access the Internet + + +@@ -713,252 +713,252 @@ Chromium is unable to recover your settings. + + Uninstall + +- +- Pin Chromium to your taskbar to get to it quickly anytime ++ ++ Pin OpenBrowser to your taskbar to get to it quickly anytime + +- +- Pin Chromium ++ ++ Pin OpenBrowser + + + +- +- Keep Chromium in your Dock to get to it quickly anytime ++ ++ Keep OpenBrowser in your Dock to get to it quickly anytime + +- ++ + Keep in Dock + + +- +- Chromium isn't your default browser ++ ++ OpenBrowser isn't your default browser + +- +- Set Chromium as your default browser and pin it to your taskbar ++ ++ Set OpenBrowser as your default browser and pin it to your taskbar + + +- +- Set Chromium as your default PDF viewer ++ ++ Set OpenBrowser as your default PDF viewer + + + + +- Extensions, apps, and themes from unknown sources can harm your device. Chromium recommends only installing them from the $1Chrome Web Store ++ Extensions, apps, and themes from unknown sources can harm your device. OpenBrowser recommends only installing them from the $1Chrome Web Store + + +- Learn why Chromium blocks some downloads ++ desc="Text for the link to the help page about why OpenBrowser blocks some downloaded files."> ++ Learn why OpenBrowser blocks some downloads + + +- This file may be dangerous$1Chromium can check this download for you if you provide the password. Info about the file gets sent to Google Safe Browsing, but the file content and password stay on your device. ++ This file may be dangerous$1OpenBrowser can check this download for you if you provide the password. Info about the file gets sent to Google Safe Browsing, but the file content and password stay on your device. + + + + +- Adding to Chromium... ++ Adding to OpenBrowser... + + + +- $1bla.exe may be dangerous, so Chromium has blocked it. ++ $1bla.exe may be dangerous, so OpenBrowser has blocked it. + + + +- This file is dangerous, so Chromium has blocked it. ++ This file is dangerous, so OpenBrowser has blocked it. + + +- $1malware.exe is dangerous, so Chromium has blocked it. ++ $1malware.exe is dangerous, so OpenBrowser has blocked it. + + +- Chromium recommends scanning this file because it may be dangerous. ++ OpenBrowser recommends scanning this file because it may be dangerous. + + + + +- Chromium blocked this download because the file type isn't commonly downloaded and it may be dangerous ++ OpenBrowser blocked this download because the file type isn't commonly downloaded and it may be dangerous + + +- Chromium blocked this download because the file is dangerous ++ OpenBrowser blocked this download because the file is dangerous + + +- Chromium blocked this download because the file can harm your personal and social network accounts ++ OpenBrowser blocked this download because the file can harm your personal and social network accounts + + +- Chromium blocked this download because the file isn't commonly downloaded and it may be dangerous ++ OpenBrowser blocked this download because the file isn't commonly downloaded and it may be dangerous + + +- Chromium blocked this download because the archive file includes other files that may hide malware ++ OpenBrowser blocked this download because the archive file includes other files that may hide malware + + +- Chromium blocked this download because the file is deceptive and may make unexpected changes to your device ++ OpenBrowser blocked this download because the file is deceptive and may make unexpected changes to your device + + +- Chromium blocked this download because the site isn't using a secure connection and the file may have been tampered with ++ OpenBrowser blocked this download because the site isn't using a secure connection and the file may have been tampered with + + +- Chromium blocked this download because you turned Safe Browsing off and the file can't be verified ++ OpenBrowser blocked this download because you turned Safe Browsing off and the file can't be verified + + + + +- Learn why Chromium blocks some files ++ Learn why OpenBrowser blocks some files + + +- Learn why Chromium blocks some files, opens in new tab ++ Learn why OpenBrowser blocks some files, opens in new tab + + + + + +- Exit Chromium anyway? ++ Exit OpenBrowser anyway? + + + + +- Quit Chromium anyway? ++ Quit OpenBrowser anyway? + + + + + + +- Chromium is in background mode. ++ OpenBrowser is in background mode. + + + + + +- Google API keys are missing. Some functionality of Chromium will be disabled. ++ Google API keys are missing. Some functionality of OpenBrowser will be disabled. + + + + + +- $1Gmail Checker has been added to Chromium ++ $1Gmail Checker has been added to OpenBrowser + + + + +- Also delete data from Chromium ($1www.google.com) ++ Also delete data from OpenBrowser ($1www.google.com) + + + + +- Chromium found that "$1Gmail Checker" contains malware ++ OpenBrowser found that "$1Gmail Checker" contains malware + + +- Chromium found that these items contain malware: ++ OpenBrowser found that these items contain malware: + + + + +- This extension is no longer supported. Chromium recommends that you remove it instead. ++ This extension is no longer supported. OpenBrowser recommends that you remove it instead. + + + {NUM_EXTENSIONS, plural, +- =1 {This extension is no longer supported. Chromium recommends that you remove it.} +- other {These extensions are no longer supported. Chromium recommends that you remove them.}} ++ =1 {This extension is no longer supported. OpenBrowser recommends that you remove it.} ++ other {These extensions are no longer supported. OpenBrowser recommends that you remove them.}} + + +- Chromium recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a> ++ OpenBrowser recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a> + + + {NUM_EXTENSIONS, plural, +- =1 {Chromium recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} +- other {Chromium recommends that you remove them. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} ++ =1 {OpenBrowser recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} ++ other {OpenBrowser recommends that you remove them. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} + } + + +- Remove $1Google Translate from Chromium ++ Remove $1Google Translate from OpenBrowser + + + + + +- This extension contains malware and is unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including your personal info. ++ This extension contains malware and is unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including your personal info. + + +- This extension violates the Chrome Web Store policy, and might be unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including your personal info. ++ This extension violates the Chrome Web Store policy, and might be unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including your personal info. + + +- This extension was unpublished by its developer, and might be unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including your personal info. ++ This extension was unpublished by its developer, and might be unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including your personal info. + + +- Chromium recommends you review this extension ++ OpenBrowser recommends you review this extension + + +- Chromium can't verify where this extension comes from, and it might be unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including personal info. ++ OpenBrowser can't verify where this extension comes from, and it might be unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including personal info. + + +- On • Chromium can't verify where this extension comes from ++ On • OpenBrowser can't verify where this extension comes from + + +- Off • Chromium can't verify where this extension comes from ++ Off • OpenBrowser can't verify where this extension comes from + + +- This extension hasn't published privacy practices, such as how it collects and uses data. Chromium recommends that you remove it. ++ This extension hasn't published privacy practices, such as how it collects and uses data. OpenBrowser recommends that you remove it. + + + + + {NUM_EXTENSIONS, plural, +- =1 {Chromium recommends that you remove it} +- other {Chromium recommends that you remove them}} ++ =1 {OpenBrowser recommends that you remove it} ++ other {OpenBrowser recommends that you remove them}} + + +- Allow extension to show access requests in the Chromium toolbar ++ Allow extension to show access requests in the OpenBrowser toolbar + +- +- Warning: Chromium cannot prevent extensions from recording your browsing history. To disable this extension in Incognito mode, unselect this option. ++ ++ Warning: OpenBrowser cannot prevent extensions from recording your browsing history. To disable this extension in Incognito mode, unselect this option. + + +- Remove from Chromium ++ Remove from OpenBrowser + + +- In Chromium ++ In OpenBrowser + + +- Changes to this setting will be applied once Chromium restarts. ++ Changes to this setting will be applied once OpenBrowser restarts. + + + + +- To make Chromium safer, we disabled some extensions that aren't listed in the $1Chrome Web Store and may have been added without your knowledge. ++ To make OpenBrowser safer, we disabled some extensions that aren't listed in the $1Chrome Web Store and may have been added without your knowledge. + + +- To make Chromium safer, we disabled the following extension that isn't listed in the $1Chrome Web Store and may have been added without your knowledge. ++ To make OpenBrowser safer, we disabled the following extension that isn't listed in the $1Chrome Web Store and may have been added without your knowledge. + + + + + +- Customize and control Chromium ++ Customize and control OpenBrowser + + + +- Customize and control Chromium. Update is available. ++ Customize and control OpenBrowser. Update is available. + + + +- Customize and control Chromium. Something needs your attention - click for details. ++ Customize and control OpenBrowser. Something needs your attention - click for details. + + + +- &Open in Chromium ++ &Open in OpenBrowser + + + +@@ -970,12 +970,12 @@ Chromium is unable to recover your settings. + + + +- About &Chromium ++ About &OpenBrowser + + + + +- Relaunch to Update &Chromium ++ Relaunch to Update &OpenBrowser + + + +@@ -987,32 +987,32 @@ Chromium is unable to recover your settings. + + + +- About &Chromium ++ About &OpenBrowser + + + + +- Relaunch to update &Chromium ++ Relaunch to update &OpenBrowser + + + + +- About &Chromium ++ About &OpenBrowser + + +- Relaunch to update &ChromiumOS ++ Relaunch to update &OpenBrowserOS + + + + + +- Chromium ++ OpenBrowser + + +- Chromium Helper ++ OpenBrowser Helper + + +- Chromium Helper ++ OpenBrowser Helper + + + +@@ -1021,24 +1021,24 @@ Chromium is unable to recover your settings. + + + +- C&ustomize Your Chromium ++ C&ustomize Your OpenBrowser + + +- Other Chromium Profiles ++ Other OpenBrowser Profiles + + +- &Manage Chromium Profiles ++ &Manage OpenBrowser Profiles + + + + +- C&ustomize your Chromium ++ C&ustomize your OpenBrowser + + +- Other Chromium profiles ++ Other OpenBrowser profiles + + +- &Manage Chromium profiles ++ &Manage OpenBrowser profiles + + + +@@ -1050,33 +1050,33 @@ Chromium is unable to recover your settings. + + + +- Chromium ++ OpenBrowser + + + + +- Sync and personalize Chromium across your devices ++ Sync and personalize OpenBrowser across your devices + + + + + +- You were signed in to Chromium as $1foo@gmail.com. Please use the same account to sign in again. ++ You were signed in to OpenBrowser as $1foo@gmail.com. Please use the same account to sign in again. + + +- Someone previously signed in to Chromium on this computer as $1user@example.com. Please create a new Chromium user to keep your information separate. ++ Someone previously signed in to OpenBrowser on this computer as $1user@example.com. Please create a new OpenBrowser user to keep your information separate. + + + + + +- Continue where you left off: Chromium restored your tabs from your last session. You can turn this off in ++ Continue where you left off: OpenBrowser restored your tabs from your last session. You can turn this off in + + +- Continue where you left off: Chromium restores your tabs every time you restart. To turn this off, go to ++ Continue where you left off: OpenBrowser restores your tabs every time you restart. To turn this off, go to + + +- Continue where you left off: Chromium can restore your tabs every time you restart. To turn this on, go to ++ Continue where you left off: OpenBrowser can restore your tabs every time you restart. To turn this on, go to + + + Settings. +@@ -1085,28 +1085,28 @@ Chromium is unable to recover your settings. + Settings, opens in new tab. + + +- +- Your organization requires you to sign into Chromium ++ ++ Your organization requires you to sign into OpenBrowser + + + +- Link your Chromium data to this account? ++ Link your OpenBrowser data to this account? + + +- You are signing in with a managed account and giving its administrator control over your Chromium profile. Your Chromium data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. $2Learn more ++ You are signing in with a managed account and giving its administrator control over your OpenBrowser profile. Your OpenBrowser data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. $2Learn more + + +- You are signing in with a managed account and giving its administrator control over your Chromium profile. Your Chromium data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. You can optionally create a new profile to keep your existing Chromium data separate. $2Learn more ++ You are signing in with a managed account and giving its administrator control over your OpenBrowser profile. Your OpenBrowser data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. You can optionally create a new profile to keep your existing OpenBrowser data separate. $2Learn more + +- +- Your organization, $1manager.com, requires you to sign into Chromium ++ ++ Your organization, $1manager.com, requires you to sign into OpenBrowser + +- +- Sign in to Chromium? ++ ++ Sign in to OpenBrowser? + + + +- You're signed in to Chromium! ++ You're signed in to OpenBrowser! + + + You're signed in as $1foo@gmail.com. Now you can access your bookmarks, history, and other settings on all your signed in devices. +@@ -1115,40 +1115,40 @@ Chromium is unable to recover your settings. + + + +- Your organization manages Chromium ++ Your organization manages OpenBrowser + + +- $1The Company manages Chromium ++ $1The Company manages OpenBrowser + + +- Multiple organizations manage Chromium ++ Multiple organizations manage OpenBrowser + + + + +- To continue, sign in to Chromium as $1user@example.com. This makes sure that you've got your organization's policies. ++ To continue, sign in to OpenBrowser as $1user@example.com. This makes sure that you've got your organization's policies. + + + + + +- The extension "$1Screencast" wants you to sign in to Chromium ++ The extension "$1Screencast" wants you to sign in to OpenBrowser + + +- To use this extension as $1elisa.g.beckett@gmail.com, sign in to Chromium. ++ To use this extension as $1elisa.g.beckett@gmail.com, sign in to OpenBrowser. + + +- An extension wants you to sign in to Chromium ++ An extension wants you to sign in to OpenBrowser + + + + + + +- Your system administrator has configured Chromium to open an alternative browser to access $1example.com. ++ Your system administrator has configured OpenBrowser to open an alternative browser to access $1example.com. + + +- Your system administrator has configured Chromium to open $2Internet Explorer to access $1example.com. ++ Your system administrator has configured OpenBrowser to open $2Internet Explorer to access $1example.com. + + + +@@ -1160,21 +1160,21 @@ Chromium is unable to recover your settings. + + + +- +- Customize Chromium ++ ++ Customize OpenBrowser + + + + +- Make Chromium Yours ++ Make OpenBrowser Yours + + + +- +- Customize Chromium to give it a new look ++ ++ Customize OpenBrowser to give it a new look + +- +- Click the Customize Chromium button on the New Tab Page to give Chromium a new look ++ ++ Click the Customize OpenBrowser button on the New Tab Page to give OpenBrowser a new look + + + +@@ -1188,263 +1188,263 @@ Chromium is unable to recover your settings. + + + +- $1foo@gmail.com was previously using Chromium ++ $1foo@gmail.com was previously using OpenBrowser + + + + + + +- Sign in to Chromium? ++ desc="Text asking the user to sign into OpenBrowser while the OpenBrowser Signin Bubble intercept is shown."> ++ Sign in to OpenBrowser? + +- +- Make Chromium your own ++ ++ Make OpenBrowser your own + + +- Use Chromium without an account ++ desc="Label of the Decline button of the OpenBrowser Signin Bubble intercept that is shown when a signed out user signs in on the web with it's first account."> ++ Use OpenBrowser without an account + + + + +- Sign In to Chromium? ++ desc="Text asking the user to sign into OpenBrowser while the OpenBrowser Signin Bubble intercept is shown."> ++ Sign In to OpenBrowser? + +- +- Make Chromium Your Own ++ ++ Make OpenBrowser Your Own + + +- Use Chromium Without an Account ++ desc="Label of the Decline button of the OpenBrowser Signin Bubble intercept that is shown when a signed out user signs in on the web with it's first account."> ++ Use OpenBrowser Without an Account + + + + + +- Sign in to Chromium in a new profile? ++ Sign in to OpenBrowser in a new profile? + + +- Switch to existing Chromium profile? ++ Switch to existing OpenBrowser profile? + +- +- You're already signed in as $1foo@gmail.com in another Chromium profile ++ ++ You're already signed in as $1foo@gmail.com in another OpenBrowser profile + +- +- To stay safer online with your parent’s choices, switch to your Chromium profile where you’re already signed in as $1foo@gmail.com ++ ++ To stay safer online with your parent’s choices, switch to your OpenBrowser profile where you’re already signed in as $1foo@gmail.com + + +- $1Elisa is already signed in to this Chromium profile. To keep your browsing separate, Chromium can create your own profile for you. ++ $1Elisa is already signed in to this OpenBrowser profile. To keep your browsing separate, OpenBrowser can create your own profile for you. + + +- $1Elisa is already signed in. To keep your browsing separate, sign in to Chromium in your own profile as $2foo@gmail.com. ++ $1Elisa is already signed in. To keep your browsing separate, sign in to OpenBrowser in your own profile as $2foo@gmail.com. + +- +- To get your passwords and more on all your devices, sign in to Chromium ++ ++ To get your passwords and more on all your devices, sign in to OpenBrowser + +- +- To get your passwords, bookmarks, and more on all your devices, sign in to Chromium ++ ++ To get your passwords, bookmarks, and more on all your devices, sign in to OpenBrowser + +- +- To stay safer online with your parent’s choices, sign in to Chromium ++ ++ To stay safer online with your parent’s choices, sign in to OpenBrowser + +- +- While you're signed in, you can use your passwords and more from your Google Account in Chromium. To change this, go to “Your account in Chromium”. ++ ++ While you're signed in, you can use your passwords and more from your Google Account in OpenBrowser. To change this, go to “Your account in OpenBrowser”. + + +- While you're signed in, you can use your passwords and more from your Google Account in Chromium. $1CTRL+SHIFT+M can change your Google services settings. ++ While you're signed in, you can use your passwords and more from your Google Account in OpenBrowser. $1CTRL+SHIFT+M can change your Google services settings. + +- +- Sign out of Chromium? ++ ++ Sign out of OpenBrowser? + +- +- Your passwords, payment methods, and addresses that you saved in your Google Account will be removed from this device. To use them again in Chromium, sign back in. ++ ++ Your passwords, payment methods, and addresses that you saved in your Google Account will be removed from this device. To use them again in OpenBrowser, sign back in. + +- +- Your passwords and other Chromium data that you saved in your Google Account will be removed from this device. To use them again in Chromium, sign back in. ++ ++ Your passwords and other OpenBrowser data that you saved in your Google Account will be removed from this device. To use them again in OpenBrowser, sign back in. + +- ++ + {count, plural, +- =1 {Chromium needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data (1 item) will be deleted.} +- other {Chromium needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data ({count} items) will be deleted.}} ++ =1 {OpenBrowser needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data (1 item) will be deleted.} ++ other {OpenBrowser needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data ({count} items) will be deleted.}} + +- ++ + {count, plural, +- =1 {Some of your Chromium data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data (1 item) will be deleted.} +- other {Some of your Chromium data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data ({count} items) will be deleted.}} ++ =1 {Some of your OpenBrowser data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data (1 item) will be deleted.} ++ other {Some of your OpenBrowser data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data ({count} items) will be deleted.}} + + +- You’ll be signed out of most sites when you close all Chromium windows, except your Google Account if you’re signed in to Chromium. To let sites remember you, $1go to settings. ++ You’ll be signed out of most sites when you close all OpenBrowser windows, except your Google Account if you’re signed in to OpenBrowser. To let sites remember you, $1go to settings. + + +- If you forgot your passphrase or want to change this setting, $1clear the Chromium data in your account ++ If you forgot your passphrase or want to change this setting, $1clear the OpenBrowser data in your account + + +- Clear the Chromium data in your account ++ Clear the OpenBrowser data in your account + + +- Your data is encrypted with your passphrase. Enter it to use and save Chromium data in your Google Account. ++ Your data is encrypted with your passphrase. Enter it to use and save OpenBrowser data in your Google Account. + + +- Click to close the Chromium sign-in dialog ++ desc="Accessibility label (read by the accessibility tools) of the avatar button when the OpenBrowser Signin bubble is shown. The text implies that the expanded bubble underneath the button is closable by clicking on the button. The actual text is 'Sign in to OpenBrowser?' with a bubble shown under it."> ++ Click to close the OpenBrowser sign-in dialog + + +- Chromium account requires re-authentication ++ desc="Accessibility label (read by the accessibility tools) of the avatar button when OpenBrowser is in 'Sign-in pending' state. This state means that the account associated with OpenBrowser does not have valid credentials anymore and needs to be re-authenticated."> ++ OpenBrowser account requires re-authentication + + + +- +- To get your passwords and more on all your devices, sign in to Chromium. This password will be saved in your Google Account after you sign in. ++ ++ To get your passwords and more on all your devices, sign in to OpenBrowser. This password will be saved in your Google Account after you sign in. + +- +- To get your addresses and more on all your devices, sign in to Chromium. This address will be saved in your Google Account after you sign in. ++ ++ To get your addresses and more on all your devices, sign in to OpenBrowser. This address will be saved in your Google Account after you sign in. + + + + + + +- Customize your new Chromium profile ++ Customize your new OpenBrowser profile + + +- Customize your Chromium profile ++ Customize your OpenBrowser profile + + + + + +- +- ChromiumOS System ++ ++ OpenBrowserOS System + + +- ChromiumOS could not sync your data because your account sign-in details are out of date. ++ OpenBrowserOS could not sync your data because your account sign-in details are out of date. + + +- ChromiumOS could not sync your data because Sync is not available for your domain. ++ OpenBrowserOS could not sync your data because Sync is not available for your domain. + + +- ChromiumOS could not sync your data due to an error signing in. ++ OpenBrowserOS could not sync your data due to an error signing in. + + + + + +- Sign in to Chromium ++ Sign in to OpenBrowser + + +- Your Chromium ++ Your OpenBrowser + + +- +- Remove account from Chromium ++ ++ Remove account from OpenBrowser + +- +- Other Chromium profiles ++ ++ Other OpenBrowser profiles + +- +- Manage Chromium profiles ++ ++ Manage OpenBrowser profiles + + +- Sign out of Chromium ++ desc="The text label of the Sign out of OpenBrowser button in the Profile Menu."> ++ Sign out of OpenBrowser + + +- Add Chromium profile ++ Add OpenBrowser profile + + + +- +- Remove Account from Chromium ++ ++ Remove Account from OpenBrowser + +- +- Other Chromium Profiles ++ ++ Other OpenBrowser Profiles + +- +- Manage Chromium Profiles ++ ++ Manage OpenBrowser Profiles + + +- Sign Out of Chromium ++ desc="The text label of the Sign out of OpenBrowser button in the Profile Menu."> ++ Sign Out of OpenBrowser + + +- Add Chromium Profile ++ Add OpenBrowser Profile + + + + + + +- Remove from Chromium... ++ Remove from OpenBrowser... + + + + +- Remove this app's data from Chromium ++ Remove this app's data from OpenBrowser + + + +- +- Chromium Apps ++ ++ OpenBrowser Apps + + +- Chromium Apps ++ OpenBrowser Apps + + +- ++ + +- ++ + + + + + + +- $1example.com requires that you read and accept the following Terms of Service before using this device. These terms do not expand, modify or limit the ChromiumOS Terms. ++ $1example.com requires that you read and accept the following Terms of Service before using this device. These terms do not expand, modify or limit the OpenBrowserOS Terms. + + + + + +- Chromium is using your camera and microphone. ++ OpenBrowser is using your camera and microphone. + + +- Chromium is using your microphone. ++ OpenBrowser is using your microphone. + + +- Chromium is using your camera. ++ OpenBrowser is using your camera. + + + + + + {NUM_DEVICES, plural, +- =0 {1 HID device was being accessed by one or more Chromium extensions} +- =1 {1 HID device is being accessed by one or more Chromium extensions} +- other {# HID devices are being accessed by one or more Chromium extensions}} ++ =0 {1 HID device was being accessed by one or more OpenBrowser extensions} ++ =1 {1 HID device is being accessed by one or more OpenBrowser extensions} ++ other {# HID devices are being accessed by one or more OpenBrowser extensions}} + + + + + {NUM_DEVICES, plural, +- =0 {1 USB device was being accessed by one or more Chromium extensions} +- =1 {1 USB device is being accessed by one or more Chromium extensions} +- other {# USB devices are being accessed by one or more Chromium extensions}} ++ =0 {1 USB device was being accessed by one or more OpenBrowser extensions} ++ =1 {1 USB device is being accessed by one or more OpenBrowser extensions} ++ other {# USB devices are being accessed by one or more OpenBrowser extensions}} + + + + + + +- The profile appears to be in use by another Chromium process ($112345) on another computer ($2example.com). Chromium has locked the profile so that it doesn't get corrupted. If you are sure no other processes are using this profile, you can unlock the profile and relaunch Chromium. ++ The profile appears to be in use by another OpenBrowser process ($112345) on another computer ($2example.com). OpenBrowser has locked the profile so that it doesn't get corrupted. If you are sure no other processes are using this profile, you can unlock the profile and relaunch OpenBrowser. + + + + + + +- Set Chromium as your default browser ++ Set OpenBrowser as your default browser + + + +@@ -1452,40 +1452,40 @@ Chromium is unable to recover your settings. + + + +- This person's browsing data will be deleted from this device. To recover the data, sign in to Chromium as $2foo@example.com. ++ This person's browsing data will be deleted from this device. To recover the data, sign in to OpenBrowser as $2foo@example.com. + + + + +- Chromium just got better ++ OpenBrowser just got better + + +- Now it's easier to use Chromium with your Google Account and on shared computers. ++ Now it's easier to use OpenBrowser with your Google Account and on shared computers. + + +- This is your Chromium ++ This is your OpenBrowser + + +- Your web, bookmarks, and other Chromium stuff live here. ++ Your web, bookmarks, and other OpenBrowser stuff live here. + + +- Guests can use Chromium without leaving anything behind. ++ Guests can use OpenBrowser without leaving anything behind. + + +- If you share a computer, friends and family can browse separately and set up Chromium just the way they want. ++ If you share a computer, friends and family can browse separately and set up OpenBrowser just the way they want. + + +- Click your name to open Chromium and start browsing. ++ Click your name to open OpenBrowser and start browsing. + + +- Add yourself to Chromium ++ Add yourself to OpenBrowser + + + + + + +- Click the Chromium menu ++ Click the OpenBrowser menu + + + Click “Password Manager” +@@ -1500,82 +1500,82 @@ Chromium is unable to recover your settings. + + + +- ''' It also controls what page is shown when you start Chromium. ''' ++ ''' It also controls what page is shown when you start OpenBrowser. ''' + + +- ''' It also controls what page is shown when you start Chromium or search from the Omnibox. ''' ++ ''' It also controls what page is shown when you start OpenBrowser or search from the Omnibox. ''' + + + + +- Discover great apps, games, extensions and themes for Chromium. ++ Discover great apps, games, extensions and themes for OpenBrowser. + + + + + +- Chromium (mDNS-In) ++ OpenBrowser (mDNS-In) + +- ++ + +- ++ + +- ++ + + +- Inbound rule for Chromium to allow mDNS traffic. ++ Inbound rule for OpenBrowser to allow mDNS traffic. + +- ++ + +- ++ + +- ++ + + + + +- +- If an image doesn’t have a useful description, Chromium will try to provide one for you. To create descriptions, images are sent to Google. You can turn this off in settings at any time. ++ ++ If an image doesn’t have a useful description, OpenBrowser will try to provide one for you. To create descriptions, images are sent to Google. You can turn this off in settings at any time. + +- +- If an image doesn’t have a useful description, Chromium will try to provide one for you. To create descriptions, images are sent to Google. ++ ++ If an image doesn’t have a useful description, OpenBrowser will try to provide one for you. To create descriptions, images are sent to Google. + + + This uses the same spell checker that's used in Google search. Text you type in the browser is sent to Google. You can always change this behavior in settings. + + + +- Open link in new Chromium &tab ++ Open link in new OpenBrowser &tab + + +- Open link in Chromium inco&gnito window ++ Open link in OpenBrowser inco&gnito window + + + + +- Open Link in New Chromium &tab ++ Open Link in New OpenBrowser &tab + + +- Open Link in Chromium Inco&gnito Window ++ Open Link in OpenBrowser Inco&gnito Window + + + + + +- Making Chromium yours... ++ Making OpenBrowser yours... + + + + + + +- Relaunch Chromium ++ Relaunch OpenBrowser + + + {COUNT, plural, +- =0 {A new update for Chromium is available and will be applied as soon as you relaunch.} +- =1 {A new update for Chromium is available and will be applied as soon as you relaunch. Your Incognito window won't reopen.} +- other {A new update for Chromium is available and will be applied as soon as you relaunch. Your # Incognito windows won't reopen.}} ++ =0 {A new update for OpenBrowser is available and will be applied as soon as you relaunch.} ++ =1 {A new update for OpenBrowser is available and will be applied as soon as you relaunch. Your Incognito window won't reopen.} ++ other {A new update for OpenBrowser is available and will be applied as soon as you relaunch. Your # Incognito windows won't reopen.}} + + + Relaunch +@@ -1583,10 +1583,10 @@ Chromium is unable to recover your settings. + + + +- Restart ChromiumOS ++ Restart OpenBrowserOS + + +- ChromiumOS needs to be restarted to apply the update. ++ OpenBrowserOS needs to be restarted to apply the update. + + + Restart +@@ -1595,71 +1595,71 @@ Chromium is unable to recover your settings. + + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + + + + +- Reinstall Chromium ++ Reinstall OpenBrowser + + + +- Chromium is Out of Date ++ OpenBrowser is Out of Date + + + + +- Chromium is out of date ++ OpenBrowser is out of date + + + +- Can't update Chromium ++ Can't update OpenBrowser + + +- Chromium couldn't update to the latest version, so you're missing out on new features and security fixes. ++ OpenBrowser couldn't update to the latest version, so you're missing out on new features and security fixes. + + + + +- Update Chromium ++ Update OpenBrowser + + +- Enter your passphrase to use and save Chromium data in your account, $1elisa.beckett@gmail.com ++ Enter your passphrase to use and save OpenBrowser data in your account, $1elisa.beckett@gmail.com + + +- Verify it's you to use and save Chromium data in your account, $1elisa.beckett@gmail.com ++ Verify it's you to use and save OpenBrowser data in your account, $1elisa.beckett@gmail.com + + +- To use and save Chromium data in your Google Account, update Chromium ++ To use and save OpenBrowser data in your Google Account, update OpenBrowser + + +- Update Chromium to keeping using the Chromium data in your Google Account, $1elisa.beckett@gmail.com ++ Update OpenBrowser to keeping using the OpenBrowser data in your Google Account, $1elisa.beckett@gmail.com + + + + +- Update Chromium to start sync ++ Update OpenBrowser to start sync + + +- Update Chromium ++ Update OpenBrowser + + + + +- Chromium is out of date ++ OpenBrowser is out of date + + + +- Update Chromium ++ Update OpenBrowser + + + + +- Update Chromium ++ Update OpenBrowser + + + +@@ -1667,92 +1667,92 @@ Chromium is unable to recover your settings. + + + +- +- Chromium will restart in $11 minute, 7 seconds ++ ++ OpenBrowser will restart in $11 minute, 7 seconds + +- +- Please restart Chromium now ++ ++ Please restart OpenBrowser now + +- +- A special security update for Chromium was just applied. Restart now and we'll restore your tabs. ++ ++ A special security update for OpenBrowser was just applied. Restart now and we'll restore your tabs. + + + + +- Chromium Tab ++ OpenBrowser Tab + + +- To share your screen, allow screen recording for Chromium in System Settings ++ To share your screen, allow screen recording for OpenBrowser in System Settings + + +- To share your screen, allow screen recording for Chromium in System Settings. ++ To share your screen, allow screen recording for OpenBrowser in System Settings. + + +- To share your window, allow screen recording for Chromium in System Settings ++ To share your window, allow screen recording for OpenBrowser in System Settings + + +- To share your window, allow screen recording for Chromium in System Settings. ++ To share your window, allow screen recording for OpenBrowser in System Settings. + + +- You'll then need to restart Chromium. ++ You'll then need to restart OpenBrowser. + + +- To share system audio, open System Settings and allow 'System Audio Recording Only' for Chromium. You'll then need to restart Chromium. ++ To share system audio, open System Settings and allow 'System Audio Recording Only' for OpenBrowser. You'll then need to restart OpenBrowser. + + + + + +- Chromium needs permission to access your camera to create a 3D map of your surroundings ++ OpenBrowser needs permission to access your camera to create a 3D map of your surroundings + + +- Chromium needs permission to access your camera for this site ++ OpenBrowser needs permission to access your camera for this site + + +- Chromium needs permission to track your hands ++ OpenBrowser needs permission to track your hands + + +- Chromium needs permission to access your microphone for this site ++ OpenBrowser needs permission to access your microphone for this site + + +- Chromium needs permission to access your camera and microphone for this site ++ OpenBrowser needs permission to access your camera and microphone for this site + + +- Chromium needs access to your location to share your location with this site ++ OpenBrowser needs access to your location to share your location with this site + + +- Chromium needs storage access to download files ++ OpenBrowser needs storage access to download files + + + +- Chromium needs camera permission to create a 3D map of your surroundings ++ OpenBrowser needs camera permission to create a 3D map of your surroundings + + +- Chromium needs camera permission for this site ++ OpenBrowser needs camera permission for this site + + +- Chromium needs permission to track your hands ++ OpenBrowser needs permission to track your hands + + +- Chromium needs microphone permission for this site ++ OpenBrowser needs microphone permission for this site + + +- Chromium needs camera and microphone permissions for this site ++ OpenBrowser needs camera and microphone permissions for this site + + +- Chromium needs location permission for this site ++ OpenBrowser needs location permission for this site + + +- Chromium needs storage access permission to download files ++ OpenBrowser needs storage access permission to download files + + +- Chromium needs permission to map your surroundings and track your hands ++ OpenBrowser needs permission to map your surroundings and track your hands + + + + + +- Once Chromium has access, websites will be able to ask you for access. ++ Once OpenBrowser has access, websites will be able to ask you for access. + + + This will allow you to select from available devices and display content on them. +@@ -1761,12 +1761,12 @@ Chromium is unable to recover your settings. + + + +- Customize Chromium ++ Customize OpenBrowser + + + + +- Chromium history ++ OpenBrowser history + + + +@@ -2175,17 +2175,17 @@ Chromium is unable to recover your settings. + + + +- Please wait while Chromium installs the latest system updates. ++ Please wait while OpenBrowser installs the latest system updates. + + +- ChromiumOS terms ++ OpenBrowserOS terms + + + + + + +- Go to Chromium notification settings ++ Go to OpenBrowser notification settings + + + +@@ -2193,115 +2193,115 @@ Chromium is unable to recover your settings. + + + {0, plural, +- =0 {A Chromium update is available} +- =1 {A Chromium update is available} +- other {A Chromium update has been available for # days}} ++ =0 {A OpenBrowser update is available} ++ =1 {A OpenBrowser update is available} ++ other {A OpenBrowser update has been available for # days}} + + + {COUNT, plural, +- =0 {Your administrator asks that you relaunch Chromium to apply this update} +- =1 {Your administrator asks that you relaunch Chromium to apply this update. Your Incognito window won't reopen.} +- other {Your administrator asks that you relaunch Chromium to apply this update. Your # Incognito windows won't reopen.}} ++ =0 {Your administrator asks that you relaunch OpenBrowser to apply this update} ++ =1 {Your administrator asks that you relaunch OpenBrowser to apply this update. Your Incognito window won't reopen.} ++ other {Your administrator asks that you relaunch OpenBrowser to apply this update. Your # Incognito windows won't reopen.}} + + + {0, plural, +- =1 {Relaunch Chromium within a day} +- other {Relaunch Chromium within # days}} ++ =1 {Relaunch OpenBrowser within a day} ++ other {Relaunch OpenBrowser within # days}} + + + {0, plural, +- =1 {Chromium will relaunch in an hour} +- other {Chromium will relaunch in # hours}} ++ =1 {OpenBrowser will relaunch in an hour} ++ other {OpenBrowser will relaunch in # hours}} + + + {0, plural, +- =1 {Chromium will relaunch in 1 minute} +- other {Chromium will relaunch in # minutes}} ++ =1 {OpenBrowser will relaunch in 1 minute} ++ other {OpenBrowser will relaunch in # minutes}} + + + {0, plural, +- =0 {Chromium will relaunch now} +- =1 {Chromium will relaunch in 1 second} +- other {Chromium will relaunch in # seconds}} ++ =0 {OpenBrowser will relaunch now} ++ =1 {OpenBrowser will relaunch in 1 second} ++ other {OpenBrowser will relaunch in # seconds}} + + + {COUNT, plural, +- =0 {Your administrator requires that you relaunch Chromium to apply an update} +- =1 {Your administrator requires that you relaunch Chromium to apply an update. Your Incognito window won't reopen.} +- other {Your administrator requires that you relaunch Chromium to apply an update. Your # Incognito windows won't reopen.}} ++ =0 {Your administrator requires that you relaunch OpenBrowser to apply an update} ++ =1 {Your administrator requires that you relaunch OpenBrowser to apply an update. Your Incognito window won't reopen.} ++ other {Your administrator requires that you relaunch OpenBrowser to apply an update. Your # Incognito windows won't reopen.}} + + + {COUNT, plural, +- =0 {Advanced Protection requires that you relaunch Chromium to apply an update} +- =1 {Advanced Protection requires that you relaunch Chromium to apply an update. Your Incognito window won't reopen.} +- other {Advanced Protection requires that you relaunch Chromium to apply an update. Your # Incognito windows won't reopen.}} ++ =0 {Advanced Protection requires that you relaunch OpenBrowser to apply an update} ++ =1 {Advanced Protection requires that you relaunch OpenBrowser to apply an update. Your Incognito window won't reopen.} ++ other {Advanced Protection requires that you relaunch OpenBrowser to apply an update. Your # Incognito windows won't reopen.}} + + + +- ++ + +- +- Launching Chromium... ++ ++ Launching OpenBrowser... + +- +- Couldn't launch Chromium. Try again. ++ ++ Couldn't launch OpenBrowser. Try again. + +- +- Relaunch Chromium ++ ++ Relaunch OpenBrowser + + + +- Share a Chromium tab ++ Share a OpenBrowser tab + + + + +- Chromium was automatically closed ++ OpenBrowser was automatically closed + +- +- Your organization closes Chromium when it isn't used for $130 minutes. Browsing data was deleted. This could include history, autofill, and downloads. ++ ++ Your organization closes OpenBrowser when it isn't used for $130 minutes. Browsing data was deleted. This could include history, autofill, and downloads. + +- +- Your organization deletes Chromium data when it isn't used for $130 minutes. This could include history, autofill, and downloads. ++ ++ Your organization deletes OpenBrowser data when it isn't used for $130 minutes. This could include history, autofill, and downloads. + +- +- Your organization closes Chromium when it isn't used for $130 minutes. ++ ++ Your organization closes OpenBrowser when it isn't used for $130 minutes. + + + + + +- Chromium will soon close ++ OpenBrowser will soon close + + +- Chromium will soon delete browsing data ++ OpenBrowser will soon delete browsing data + + +- Chromium will soon close and delete data ++ OpenBrowser will soon close and delete data + +- ++ + {COUNT, plural, +- =1 {Your organization automatically closes Chromium when it isn't used for 1 minute.} +- other {Your organization automatically closes Chromium when it isn't used for # minutes.}} ++ =1 {Your organization automatically closes OpenBrowser when it isn't used for 1 minute.} ++ other {Your organization automatically closes OpenBrowser when it isn't used for # minutes.}} + +- ++ + {COUNT, plural, +- =1 {Your organization automatically deletes browsing data when Chromium isn't used for 1 minute. This could include history, autofill, and downloads. Your tabs will stay open.} +- other {Your organization automatically deletes browsing data when Chromium isn't used for # minutes. This could include history, autofill, and downloads. Your tabs will stay open.}} ++ =1 {Your organization automatically deletes browsing data when OpenBrowser isn't used for 1 minute. This could include history, autofill, and downloads. Your tabs will stay open.} ++ other {Your organization automatically deletes browsing data when OpenBrowser isn't used for # minutes. This could include history, autofill, and downloads. Your tabs will stay open.}} + +- ++ + {COUNT, plural, +- =1 {Your organization automatically closes Chromium when it isn't used for 1 minute. Browsing data is deleted. This could include history, autofill, and downloads.} +- other {Your organization automatically closes Chromium when it isn't used for # minutes. Browsing data is deleted. This could include history, autofill, and downloads.}} ++ =1 {Your organization automatically closes OpenBrowser when it isn't used for 1 minute. Browsing data is deleted. This could include history, autofill, and downloads.} ++ other {Your organization automatically closes OpenBrowser when it isn't used for # minutes. Browsing data is deleted. This could include history, autofill, and downloads.}} + + +- Continue using Chromium ++ Continue using OpenBrowser + + + + + +- Help us improve Chromium ++ Help us improve OpenBrowser + + + +@@ -2315,129 +2315,129 @@ Chromium is unable to recover your settings. + + + +- Your parent has turned off "Permissions for sites, apps and extensions" for Chromium ++ Your parent has turned off "Permissions for sites, apps and extensions" for OpenBrowser + + + +- Another program on your computer added an app that may change the way Chromium works. ++ Another program on your computer added an app that may change the way OpenBrowser works. + + $1Babylon Toolbar + + +- Another program on your computer added an extension that may change the way Chromium works. ++ Another program on your computer added an extension that may change the way OpenBrowser works. + + $1Babylon Toolbar + + +- Another program on your computer added a theme that may change the way Chromium works. ++ Another program on your computer added a theme that may change the way OpenBrowser works. + + $1Babylon Toolbar + + +- $1Google has added an extension that may change the way Chromium works. ++ $1Google has added an extension that may change the way OpenBrowser works. + + $2Babylon Toolbar + + +- Remove from Chromium ++ Remove from OpenBrowser + + + + + + +- Your organization can see and manage browsing data, such as your bookmarks, history, and passwords. It can't see browsing data in other Chromium profiles ++ Your organization can see and manage browsing data, such as your bookmarks, history, and passwords. It can't see browsing data in other OpenBrowser profiles + + + +- Welcome to Chromium profiles ++ Welcome to OpenBrowser profiles + +- +- Who's using Chromium? ++ ++ Who's using OpenBrowser? + + +- Keep everything in Chromium ++ Keep everything in OpenBrowser + + +- With Chromium profiles, you can separate all your Chromium stuff. Create profiles for friends and family, or split between work and fun. ++ With OpenBrowser profiles, you can separate all your OpenBrowser stuff. Create profiles for friends and family, or split between work and fun. + + +- Chromium profiles let you keep personal browsing and work apart. Add a new profile now. ++ OpenBrowser profiles let you keep personal browsing and work apart. Add a new profile now. + + +- Chromium profiles help you separate different parts of your life. Add a new profile now. ++ OpenBrowser profiles help you separate different parts of your life. Add a new profile now. + + +- Add a new Chromium profile to keep bookmarks, passwords, and settings apart. ++ Add a new OpenBrowser profile to keep bookmarks, passwords, and settings apart. + + +- Set up your new Chromium profile ++ Set up your new OpenBrowser profile + + +- Each profile holds its own Chromium info like bookmarks, history, passwords, and more ++ Each profile holds its own OpenBrowser info like bookmarks, history, passwords, and more + + +- If you share a device, friends and family can browse separately and set up Chromium just the way they want ++ If you share a device, friends and family can browse separately and set up OpenBrowser just the way they want + + +- Switch to existing Chromium profile? ++ Switch to existing OpenBrowser profile? + + +- A Chromium profile with this account already exists on this device ++ A OpenBrowser profile with this account already exists on this device + + +- To use this profile with Glic, open Chromium and sign in ++ To use this profile with Glic, open OpenBrowser and sign in + + + + +- Sign in to Chromium ++ desc="This string appears as a heading on a full-page screen that asks the user to sign in to OpenBrowser with their Google Account. It appears when the user launches OpenBrowser for the first time. When they sign in, they can personalize and customize OpenBrowser and remember their settings in their Google Account. The tone should be inviting and alluring."> ++ Sign in to OpenBrowser + + + +- +- Set Chromium as your default browser ++ ++ Set OpenBrowser as your default browser + +- +- Use Chromium by default and get it pinned ++ ++ Use OpenBrowser by default and get it pinned + +- +- Use Chromium anytime you click links in messages, documents, and other apps ++ ++ Use OpenBrowser anytime you click links in messages, documents, and other apps + +- +- Open links in Chromium from any app. Plus for easy access, it gets pinned to your taskbar. ++ ++ Open links in OpenBrowser from any app. Plus for easy access, it gets pinned to your taskbar. + +- +- Chromium logo inside a computer screen. ++ ++ OpenBrowser logo inside a computer screen. + + +- Customize and control Chromium. Set Chromium as your default. ++ Customize and control OpenBrowser. Set OpenBrowser as your default. + + +- Set Chromium as your default ++ Set OpenBrowser as your default + +- +- Set Chromium as your default browser ++ ++ Set OpenBrowser as your default browser + + + + +- You can switch between Chromium profiles here ++ You can switch between OpenBrowser profiles here + + +- $1CTRL+SHIFT+M can switch between Chromium profiles ++ $1CTRL+SHIFT+M can switch between OpenBrowser profiles + + +- You can switch to see passwords from another Chromium profile ++ You can switch to see passwords from another OpenBrowser profile + + + +- +- To remove your Google Account from Chromium, sign out ++ ++ To remove your Google Account from OpenBrowser, sign out + +- +- To remove your Google Account from Chromium, sign out of Chromium in the Settings page ++ ++ To remove your Google Account from OpenBrowser, sign out of OpenBrowser in the Settings page + + + +@@ -2451,20 +2451,20 @@ Chromium is unable to recover your settings. + + + +- Your changes will take effect the next time you relaunch Chromium. ++ Your changes will take effect the next time you relaunch OpenBrowser. + + + + +- Chromium needs Bluetooth access to explore Bluetooth devices. $1Open Preferences ++ OpenBrowser needs Bluetooth access to explore Bluetooth devices. $1Open Preferences + + + + +- Get Chromium's strongest security ++ Get OpenBrowser's strongest security + + +- Get Chromium's strongest security ++ Get OpenBrowser's strongest security + + + Enhanced protection does more to block phishing and malware +@@ -2478,24 +2478,24 @@ Chromium is unable to recover your settings. + + + +- Speeds up sites with Chromium's V8 engine but makes Chromium slightly less resistant to attacks. This setting is on. ++ Speeds up sites with OpenBrowser's V8 engine but makes OpenBrowser slightly less resistant to attacks. This setting is on. + + +- Speeds up sites with Chromium's V8 engine but makes Chromium slightly less resistant to attacks. This setting is off. ++ Speeds up sites with OpenBrowser's V8 engine but makes OpenBrowser slightly less resistant to attacks. This setting is off. + + +- Speeds up sites with Chromium's V8 engine but makes Chromium slightly less resistant to attacks ++ Speeds up sites with OpenBrowser's V8 engine but makes OpenBrowser slightly less resistant to attacks + + +- Chromium runs faster and features that use JavaScript should work as designed ++ OpenBrowser runs faster and features that use JavaScript should work as designed + + +- Reduces performance but makes Chromium more resistant to attacks ++ Reduces performance but makes OpenBrowser more resistant to attacks + +- ++ + + +- Chromium ++ OpenBrowser + + + No update is available. +@@ -2504,7 +2504,7 @@ Chromium is unable to recover your settings. + Installation failed. Please try again. + + +- $1Chromium Installer ++ $1OpenBrowser Installer + + + Close +@@ -2543,13 +2543,13 @@ Chromium is unable to recover your settings. + Canceling... + + +- Thanks for installing. You must restart your browser before using $1Chromium. ++ Thanks for installing. You must restart your browser before using $1OpenBrowser. + + +- Thanks for installing. You must restart all your browsers before using $1Chromium. ++ Thanks for installing. You must restart all your browsers before using $1OpenBrowser. + + +- Thanks for installing. You must restart your computer before using $1Chromium. ++ Thanks for installing. You must restart your computer before using $1OpenBrowser. + + + Close +@@ -2609,7 +2609,7 @@ Chromium is unable to recover your settings. + + +- Unable to connect to the Internet. If you use a firewall, please ensure $1ChromiumUpdater.exe is in the allowlist. ++ Unable to connect to the Internet. If you use a firewall, please ensure $1OpenBrowserUpdater.exe is in the allowlist. + + +@@ -2735,22 +2735,22 @@ Chromium is unable to recover your settings. + + +- Chromium Updater Service ++ OpenBrowser Updater Service + + +- Chromium Updater Internal Service ++ OpenBrowser Updater Internal Service + + +- Keeps your Chromium software up to date. If this service is disabled or stopped, your Chromium software will not be kept up to date, meaning security vulnerabilities that may arise cannot be fixed and features may not work. This service uninstalls itself when there is no Chromium software using it. ++ Keeps your OpenBrowser software up to date. If this service is disabled or stopped, your OpenBrowser software will not be kept up to date, meaning security vulnerabilities that may arise cannot be fixed and features may not work. This service uninstalls itself when there is no OpenBrowser software using it. + + + + + + +- While this tab was inactive, memory was freed up to keep Chromium fast. You can choose to always exclude this site from being inactive. ++ While this tab was inactive, memory was freed up to keep OpenBrowser fast. You can choose to always exclude this site from being inactive. + + + +@@ -2758,12 +2758,12 @@ Chromium is unable to recover your settings. + + + +- Make Chromium Faster ++ Make OpenBrowser Faster + + + + +- Make Chromium faster ++ Make OpenBrowser faster + + + +@@ -2771,70 +2771,70 @@ Chromium is unable to recover your settings. + + + +- These tabs are using extra resources. To improve your performance, let Chromium make them inactive. ++ These tabs are using extra resources. To improve your performance, let OpenBrowser make them inactive. + + +- This tab is using extra resources. To improve your performance, let Chromium make it inactive. ++ This tab is using extra resources. To improve your performance, let OpenBrowser make it inactive. + + + + {NUM_TABS, plural, +- =1 {Chromium Recommends Pausing the Tab Slowing Your Browser} +- other {Chromium Recommends Pausing the Tabs Slowing Your Browser}} ++ =1 {OpenBrowser Recommends Pausing the Tab Slowing Your Browser} ++ other {OpenBrowser Recommends Pausing the Tabs Slowing Your Browser}} + + + + + {NUM_TABS, plural, +- =1 {Chromium recommends pausing the tab slowing your browser} +- other {Chromium recommends pausing the tabs slowing your browser}} ++ =1 {OpenBrowser recommends pausing the tab slowing your browser} ++ other {OpenBrowser recommends pausing the tabs slowing your browser}} + + + + + + +- To delete browsing data from this device only, while keeping it in your Google Account, <a href="#" target="_blank">sign out of Chromium</a>. ++ To delete browsing data from this device only, while keeping it in your Google Account, <a href="#" target="_blank">sign out of OpenBrowser</a>. + + + + +- +- Shortcuts open in Chromium ++ ++ Shortcuts open in OpenBrowser + + + + +- Chromium Shortcut ++ OpenBrowser Shortcut + + + + + + +- Cleared Chromium data ++ Cleared OpenBrowser data + + + + + + +- Try Gemini in Chromium ++ Try Gemini in OpenBrowser + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + +- Close Gemini in Chromium ++ Close Gemini in OpenBrowser + + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + + Open Gemini (Canary) +@@ -2846,7 +2846,7 @@ Chromium is unable to recover your settings. + Open Gemini (Beta) + + +- Close Gemini in Chromium ++ Close Gemini in OpenBrowser + + + Close Gemini (Canary) +@@ -2858,7 +2858,7 @@ Chromium is unable to recover your settings. + Close Gemini (Beta) + + +- Toggle Gemini in Chromium ++ Toggle Gemini in OpenBrowser + + + Toggle Gemini (Canary) +@@ -2870,76 +2870,76 @@ Chromium is unable to recover your settings. + Toggle Gemini (Beta) + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + +- Close Gemini in Chromium ++ Close Gemini in OpenBrowser + + +- Toggle Gemini in Chromium ++ Toggle Gemini in OpenBrowser + + +- To use Gemini in Chromium, sign in with a different Google Account ++ To use Gemini in OpenBrowser, sign in with a different Google Account + + + + +- Gemini in Chromium ++ Gemini in OpenBrowser + + +- Gemini in Chromium ++ Gemini in OpenBrowser + + +- Gemini in Chromium ++ Gemini in OpenBrowser + + + + +- Choose a Chromium profile to use with <span class="glic-brand-style">Glic</span> ++ Choose a OpenBrowser profile to use with <span class="glic-brand-style">Glic</span> + + +- Sign into Chromium with your Google Account to use <span class="glic-brand-style">Glic</span> ++ Sign into OpenBrowser with your Google Account to use <span class="glic-brand-style">Glic</span> + + +- Select the Chromium profile linked to your Google Account to personalize your Glic experience ++ Select the OpenBrowser profile linked to your Google Account to personalize your Glic experience + + +- To add a new profile and use it with Glic, sign in to Chromium with a Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to sign in to Chromium</a> ++ To add a new profile and use it with Glic, sign in to OpenBrowser with a Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to sign in to OpenBrowser</a> + + +- To add a new profile and use it with Glic, sign in to Chromium with a different Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to add a new Chromium profile</a> ++ To add a new profile and use it with Glic, sign in to OpenBrowser with a different Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to add a new OpenBrowser profile</a> + + + + +- To open Gemini in Chromium, press $1⌘+G ++ To open Gemini in OpenBrowser, press $1⌘+G + + + + + + +- To get this extension and more on all your computers, sign in to Chromium ++ To get this extension and more on all your computers, sign in to OpenBrowser + + + + + +- To get this bookmark and more on all your devices, sign in to Chromium ++ To get this bookmark and more on all your devices, sign in to OpenBrowser + + + + +- Get more when you’re signed in to Chromium ++ Get more when you’re signed in to OpenBrowser + + +- You’ll save and use passwords and more in your Google Account whenever you’re signed in to Chromium. $1Learn more ++ You’ll save and use passwords and more in your Google Account whenever you’re signed in to OpenBrowser. $1Learn more + + + Got it + + +- You now have more features available in Chromium ++ You now have more features available in OpenBrowser + + + Manage +@@ -2949,12 +2949,12 @@ Chromium is unable to recover your settings. + + + +- Your Account in Chromium ++ Your Account in OpenBrowser + + + + +- Your account in Chromium ++ Your account in OpenBrowser + + + +@@ -2962,30 +2962,30 @@ Chromium is unable to recover your settings. + + + +- Download Chromium on your phone to add an extra layer of protection when you're on the go ++ Download OpenBrowser on your phone to add an extra layer of protection when you're on the go + + +- Stay safer on the go with Enhanced Safe Browsing on Chromium for iOS ++ Stay safer on the go with Enhanced Safe Browsing on OpenBrowser for iOS + + +- Sign in faster to sites using saved passwords for Chromium on iOS ++ Sign in faster to sites using saved passwords for OpenBrowser on iOS + + +- You'll see a prompt to try $1Google Lens next time you open Chromium iOS. ++ You'll see a prompt to try $1Google Lens next time you open OpenBrowser iOS. + + +- Next time you open Chromium on your $1iPhone, you'll see a prompt to use Google Password Manager. ++ Next time you open OpenBrowser on your $1iPhone, you'll see a prompt to use Google Password Manager. + + + + + ++ desc="Title of the notification shown when OpenBrowser resets the default search engine (DSE) due to preference tampering."> + Your settings were changed by an unknown app + + +- Your default search engine was changed from outside of Chromium. To protect you, Chromium reset it. ++ desc="Body text of the notification shown when OpenBrowser resets the default search engine, explaining that a change from outside OpenBrowser was detected."> ++ Your default search engine was changed from outside of OpenBrowser. To protect you, OpenBrowser reset it. + + +diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd +index 87032bcf74573..46e0a70ccd789 100644 +--- a/chrome/app/generated_resources.grd ++++ b/chrome/app/generated_resources.grd +@@ -1644,7 +1644,7 @@ are declared in tools/grit/grit_args.gni. + Name &window... + + +- Chrome &Labs... ++ OpenBrowser &Labs... + + + +@@ -1694,7 +1694,7 @@ are declared in tools/grit/grit_args.gni. + Name &Window... + + +- Chrome &Labs... ++ OpenBrowser &Labs... + + + +@@ -1782,7 +1782,7 @@ are declared in tools/grit/grit_args.gni. + Manage Extensions + + +- Visit Chrome Web Store ++ Visit OpenBrowser Web Store + + + Performance +@@ -1841,7 +1841,7 @@ are declared in tools/grit/grit_args.gni. + Manage Extensions + + +- Visit Chrome Web Store ++ Visit OpenBrowser Web Store + + + Performance +@@ -7852,7 +7852,7 @@ Keep your key file in a safe place. You will need it to create new versions of y + Cards + + +- Default Chrome ++ Default OpenBrowser + + + Change theme +@@ -7860,7 +7860,7 @@ Keep your key file in a safe place. You will need it to create new versions of y + + Footer + +- ++ + Search tools + + +@@ -7873,10 +7873,10 @@ Keep your key file in a safe place. You will need it to create new versions of y + $1ZomboCom is managing your new tab page, opens in a new tab + + +- Reset to Default Chrome ++ Reset to Default OpenBrowser + + +- Theme updated to Default Chrome ++ Theme updated to Default OpenBrowser + + + Theme updated to uploaded image +diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd +index 87c3c8382e602..d38aa879d082b 100644 +--- a/chrome/app/theme/theme_resources.grd ++++ b/chrome/app/theme/theme_resources.grd +@@ -160,6 +160,7 @@ + + + ++ + + + +diff --git a/chrome/browser/favicon/favicon_utils.cc b/chrome/browser/favicon/favicon_utils.cc +index eff6b7ccc596b..774d653bdcc98 100644 +--- a/chrome/browser/favicon/favicon_utils.cc ++++ b/chrome/browser/favicon/favicon_utils.cc +@@ -213,34 +213,16 @@ gfx::ImageSkia ThemeFavicon(const gfx::ImageSkia& source, + SkColor alternate_color, + SkColor active_background, + SkColor inactive_background) { +- // Choose between leaving the image as-is or masking with |alternate_color|. +- const SkColor original_color = +- color_utils::CalculateKMeanColorOfBitmap(*source.bitmap()); +- +- // Compute the minimum contrast of each color against active and inactive +- // backgrounds. +- const float original_contrast = std::min( +- color_utils::GetContrastRatio(original_color, active_background), +- color_utils::GetContrastRatio(original_color, inactive_background)); +- const float alternate_contrast = std::min( +- color_utils::GetContrastRatio(alternate_color, active_background), +- color_utils::GetContrastRatio(alternate_color, inactive_background)); +- +- // Recolor the image if the original has low minimum contrast and recoloring +- // will improve it. +- return ((original_contrast < color_utils::kMinimumVisibleContrastRatio) && +- (alternate_contrast > original_contrast)) +- ? gfx::ImageSkiaOperations::CreateColorMask(source, +- alternate_color) +- : source; ++ // Always apply the alternate color (black/white theme) ++ return gfx::ImageSkiaOperations::CreateColorMask(source, alternate_color); + } + + gfx::ImageSkia ThemeMonochromeFavicon(const gfx::ImageSkia& source, + SkColor background) { +- return (color_utils::GetContrastRatio(gfx::kGoogleGrey900, background) > ++ return (color_utils::GetContrastRatio(SK_ColorBLACK, background) > + color_utils::GetContrastRatio(SK_ColorWHITE, background)) + ? gfx::ImageSkiaOperations::CreateColorMask(source, +- gfx::kGoogleGrey900) ++ SK_ColorBLACK) + : gfx::ImageSkiaOperations::CreateColorMask(source, SK_ColorWHITE); + } + +diff --git a/chrome/browser/resources/new_tab_page/app.css b/chrome/browser/resources/new_tab_page/app.css +index e478fea59f056..7f971831f25b6 100644 +--- a/chrome/browser/resources/new_tab_page/app.css ++++ b/chrome/browser/resources/new_tab_page/app.css +@@ -57,18 +57,18 @@ + */ + :host([realbox-can-show-secondary-side][realbox-had-secondary-side]), + :host([realbox-can-show-secondary-side]) { +- --ntp-search-box-width: 746px; ++ --ntp-search-box-width: 900px; + } + + @media (min-width: 560px) { + :host { +- --ntp-search-box-width: 449px; ++ --ntp-search-box-width: 600px; + } + } + + @media (min-width: 672px) { + :host { +- --ntp-search-box-width: 561px; ++ --ntp-search-box-width: 750px; + } + } + +diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts +index 167ae9b24c89f..b3e65a5d99076 100644 +--- a/chrome/browser/resources/new_tab_page/app.ts ++++ b/chrome/browser/resources/new_tab_page/app.ts +@@ -1160,10 +1160,8 @@ export class AppElement extends AppElementBase { + } + + protected computeShowBrowserPromo_(): boolean { +- return !this.modulesEnabled_ || +- (this.modulesLoadedStatus_ !== +- ModuleLoadStatus.MODULE_LOAD_IN_PROGRESS && +- !this.modulesShownToUser); ++ // Disabled: Don't show "Make OpenBrowser Yours" setup list ++ return false; + } + + protected recordBrowserPromoMetrics_() { +diff --git a/chrome/browser/resources/new_tab_page/icons/BUILD.gn b/chrome/browser/resources/new_tab_page/icons/BUILD.gn +index 3ebefc4d55512..a21d09c60109d 100644 +--- a/chrome/browser/resources/new_tab_page/icons/BUILD.gn ++++ b/chrome/browser/resources/new_tab_page/icons/BUILD.gn +@@ -16,7 +16,8 @@ generate_grd("build_grdp") { + "drive_logo.svg", + "facebook.svg", + "generic_globe.svg", +- "google_logo.svg", ++ "openbrowser_logo_white.png", ++ "openbrowser_logo_black.png", + "info.svg", + "link.svg", + "mail.svg", +diff --git a/chrome/browser/resources/new_tab_page/logo.css b/chrome/browser/resources/new_tab_page/logo.css +index e744ffca3bf37..53c71d3ece9b0 100644 +--- a/chrome/browser/resources/new_tab_page/logo.css ++++ b/chrome/browser/resources/new_tab_page/logo.css +@@ -25,18 +25,18 @@ + #logo { + forced-color-adjust: none; + height: 92px; +- width: 272px; ++ width: 830px; ++ background-repeat: no-repeat; ++ background-size: contain; ++ background-position: center; + } + +-:host([single-colored]) #logo { +- -webkit-mask-image: url(./icons/google_logo.svg); +- -webkit-mask-repeat: no-repeat; +- -webkit-mask-size: 100%; +- background-color: var(--ntp-logo-color); ++:host([is-dark]) #logo { ++ background-image: url(./icons/openbrowser_logo_white.png); + } + +-:host(:not([single-colored])) #logo { +- background-image: url(./icons/google_logo.svg); ++:host(:not([is-dark])) #logo { ++ background-image: url(./icons/openbrowser_logo_black.png); + } + + #imageDoodle { +diff --git a/chrome/browser/resources/new_tab_page/logo.ts b/chrome/browser/resources/new_tab_page/logo.ts +index ac93b867d21c4..fea17c4478205 100644 +--- a/chrome/browser/resources/new_tab_page/logo.ts ++++ b/chrome/browser/resources/new_tab_page/logo.ts +@@ -52,6 +52,11 @@ export class LogoElement extends CrLitElement { + */ + theme: {type: Object}, + ++ isDark: { ++ reflect: true, ++ type: Boolean, ++ }, ++ + loaded_: {type: Boolean}, + doodle_: {type: Object}, + imageDoodle_: {type: Object}, +@@ -78,6 +83,7 @@ export class LogoElement extends CrLitElement { + + accessor singleColored: boolean = false; + accessor theme: Theme|null = null; ++ accessor isDark: boolean = false; + private accessor loaded_: boolean = false; + protected accessor doodle_: Doodle|null = null; + protected accessor imageDoodle_: ImageDoodle|null = null; +@@ -143,6 +149,7 @@ export class LogoElement extends CrLitElement { + override willUpdate(changedProperties: PropertyValues) { + super.willUpdate(changedProperties); + ++ this.isDark = !!(this.theme && this.theme.isDark); + this.imageDoodle_ = this.computeImageDoodle_(); + this.imageUrl_ = this.computeImageUrl_(); + this.animationUrl_ = this.computeAnimationUrl_(); +diff --git a/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg b/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg +index 83221a8e6f90f..ea3bc8cf4b002 100644 +--- a/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg ++++ b/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg +@@ -1 +1,77 @@ +- +\ No newline at end of file ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc +index 8634cbb4dc17a..ef53ad2540d79 100644 +--- a/chrome/browser/themes/theme_service_factory.cc ++++ b/chrome/browser/themes/theme_service_factory.cc +@@ -139,6 +139,7 @@ void ThemeServiceFactory::RegisterProfilePrefs( + registry->RegisterIntegerPref( + prefs::kDeprecatedUserColorDoNotUse, SK_ColorTRANSPARENT, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); ++ // Use transparent to indicate no custom color (will use baseline grayscale) + registry->RegisterIntegerPref(prefs::kUserColor, SK_ColorTRANSPARENT); + registry->RegisterIntegerPref( + prefs::kDeprecatedBrowserColorVariantDoNotUse, +diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +index 350f052b92aef..36dec424c89f2 100644 +--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +@@ -407,7 +407,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) + : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorSearchboxForeground] = +- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) + : ui::ColorTransform(SK_ColorBLACK)}; + mixer[kColorSearchboxPlaceholder] = + {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) +@@ -440,7 +440,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) + : gfx::kGoogleBlue600}; + mixer[kColorSearchboxResultsForeground] = +- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) + : ui::ColorTransform(SK_ColorBLACK)}; + mixer[kColorSearchboxResultsForegroundDimmed] = + {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) +diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +index 3544f1b569ee1..760b5a59e82df 100644 +--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc ++++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +@@ -626,7 +626,7 @@ gfx::RoundedCornersF IconLabelBubbleView::GetCornerRadii() const { + if (radii_.has_value()) { + return radii_.value(); + } +- return gfx::RoundedCornersF(GetPreferredSize().height() / 2); ++ return gfx::RoundedCornersF(4); + } + + void IconLabelBubbleView::SetCornerRadii(const gfx::RoundedCornersF& radii) { +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc +index 2dbe7d318cd7b..989abffe08143 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc +@@ -245,7 +245,7 @@ LocationBarView::LocationBarView(Browser* browser, + !v->GetOmniboxController()->IsPopupOpen(); + })); + views::FocusRing::Get(this)->SetOutsetFocusRingDisabled(true); +- views::InstallPillHighlightPathGenerator(this); ++ views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), 8); + + #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) + if (features::IsOsLevelGeolocationPermissionSupportEnabled()) { +diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc +index d5306a85b1e0c..40c9d0ffd3971 100644 +--- a/chrome/browser/ui/views/tabs/tab.cc ++++ b/chrome/browser/ui/views/tabs/tab.cc +@@ -372,8 +372,20 @@ void Tab::Layout(PassKey) { + + // The bounds for the favicon will include extra width for the attention + // indicator, but visually it will be smaller at kFaviconSize wide. +- gfx::Rect favicon_bounds(start, contents_rect.y(), 0, 0); ++ ++ gfx::Rect favicon_bounds; + if (showing_icon_) { ++ const gfx::Size icon_size = icon_->GetPreferredSize(); ++ const gfx::Insets icon_insets = icon_->GetInsets(); ++ ++ // Center the favicon vertically so its middle aligns with the content area ++ // middle. We need to add the inset back because Inset(-insets) will ++ // subtract it later. ++ const int content_middle_y = contents_rect.y() + contents_rect.height() / 2; ++ const int favicon_y = content_middle_y - icon_size.height() / 2 + icon_insets.top(); ++ ++ favicon_bounds = gfx::Rect(start, favicon_y, 0, 0); ++ + if (center_icon_) { + // When centering the favicon, the favicon is allowed to escape the normal + // contents rect. +@@ -389,7 +401,9 @@ void Tab::Layout(PassKey) { + + // Add space for insets outside the favicon bounds. + favicon_bounds.Inset(-icon_->GetInsets()); +- favicon_bounds.set_size(icon_->GetPreferredSize()); ++ favicon_bounds.set_size(icon_size); ++ } else { ++ favicon_bounds = gfx::Rect(start, contents_rect.y(), 0, 0); + } + icon_->SetBoundsRect(favicon_bounds); + icon_->SetVisible(showing_icon_); +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +index 832ca90c1538c..ce053294b3ad0 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +@@ -616,13 +616,8 @@ void NewTabPageHandler::GetMostVisitedSettings( + } + + void NewTabPageHandler::GetDoodle(GetDoodleCallback callback) { +- search_provider_logos::LogoCallbacks callbacks; +- callbacks.on_cached_encoded_logo_available = +- base::BindOnce(&NewTabPageHandler::OnLogoAvailable, +- weak_ptr_factory_.GetWeakPtr(), std::move(callback)); +- // This will trigger re-downloading the doodle and caching it. This means a +- // new doodle will be returned on subsequent NTP loads. +- logo_service_->GetLogo(std::move(callbacks), /*for_webui_ntp=*/true); ++ // Disable Google doodle downloading - always return null to use local logo ++ std::move(callback).Run(nullptr); + } + + void NewTabPageHandler::UpdatePromoData() { +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +index 12651b3c1e9b0..ff46a3238a763 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +@@ -211,9 +211,8 @@ content::WebUIDataSource* CreateAndAddNewTabPageUiHtmlSource(Profile* profile) { + source->AddBoolean( + "ntpNextFeaturesEnabled", + base::FeatureList::IsEnabled(ntp_features::kNtpNextFeatures)); +- source->AddBoolean( +- "oneGoogleBarEnabled", +- base::FeatureList::IsEnabled(ntp_features::kNtpOneGoogleBar)); ++ // Disable One Google Bar (contains Gmail and Images links) ++ source->AddBoolean("oneGoogleBarEnabled", false); + source->AddBoolean("shortcutsEnabled", + base::FeatureList::IsEnabled(ntp_features::kNtpShortcuts)); + source->AddBoolean("logoEnabled", +@@ -577,10 +576,8 @@ content::WebUIDataSource* CreateAndAddNewTabPageUiHtmlSource(Profile* profile) { + ContextualSearchSourceToString( + contextual_search::ContextualSearchSource::kNewTabPage)); + +- source->AddBoolean( +- "searchboxShowComposeEntrypoint", +- (ntp_composebox::IsNtpSearchboxComposeEntrypointEnabled(profile) || +- ntp_composebox::IsNtpComposeboxEnabled(profile))); ++ // Disable AI Mode button ++ source->AddBoolean("searchboxShowComposeEntrypoint", false); + + if (ntp_realbox::IsNtpRealboxNextEnabled(profile)) { + switch (ntp_realbox::kSteadyPlaceholder.Get()) { +diff --git a/components/omnibox/browser/vector_icons/product_chrome_refresh.icon b/components/omnibox/browser/vector_icons/product_chrome_refresh.icon +index 5c35bda0d736b..2f3d804fbb80e 100644 +--- a/components/omnibox/browser/vector_icons/product_chrome_refresh.icon ++++ b/components/omnibox/browser/vector_icons/product_chrome_refresh.icon +@@ -1,51 +1,25 @@ +-// Copyright 2023 The Chromium Authors +-// Use of this source code is governed by a BSD-style license that can be +-// found in the LICENSE file. ++CANVAS_DIMENSIONS, 40, + +-CANVAS_DIMENSIONS, 15, +-MOVE_TO, 4.92, 7.5, +-R_CUBIC_TO, 0, 0.71, 0.25, 1.31, 0.76, 1.82, +-R_CUBIC_TO, 0.51, 0.51, 1.12, 0.76, 1.82, 0.76, +-R_CUBIC_TO, 0.7, 0, 1.31, -0.25, 1.82, -0.76, +-R_CUBIC_TO, 0.51, -0.51, 0.76, -1.12, 0.76, -1.82, +-R_CUBIC_TO, 0, -0.7, -0.25, -1.31, -0.76, -1.82, +-R_ARC_TO, 2.49, 2.49, 0, 0, 0, -1.82, -0.76, +-R_CUBIC_TO, -0.7, 0, -1.31, 0.25, -1.82, 0.76, +-R_ARC_TO, 2.49, 2.49, 0, 0, 0, -0.76, 1.82, ++MOVE_TO, 0, 0, ++H_LINE_TO, 30, ++V_LINE_TO, 40, ++H_LINE_TO, 0, + CLOSE, +-MOVE_TO, 7.5, 11.48, +-R_CUBIC_TO, 0.14, 0, 0.28, 0, 0.41, -0.02, +-R_CUBIC_TO, 0.13, -0.01, 0.26, -0.04, 0.39, -0.07, +-LINE_TO, 6.77, 14.06, +-R_CUBIC_TO, -1.65, -0.19, -3.04, -0.89, -4.15, -2.12, +-CUBIC_TO, 1.5, 10.71, 0.94, 9.24, 0.94, 7.55, +-R_CUBIC_TO, 0, -0.46, 0.05, -0.9, 0.13, -1.33, +-R_CUBIC_TO, 0.08, -0.44, 0.22, -0.85, 0.39, -1.25, +-R_LINE_TO, 2.63, 4.55, +-R_CUBIC_TO, 0.34, 0.59, 0.81, 1.07, 1.41, 1.43, +-R_CUBIC_TO, 0.6, 0.36, 1.26, 0.54, 2.01, 0.54, ++ ++MOVE_TO, 8, 7.5, ++H_LINE_TO, 23, ++V_LINE_TO, 15.5, ++H_LINE_TO, 8, + CLOSE, +-R_MOVE_TO, 0, -7.87, +-R_CUBIC_TO, -0.87, 0, -1.65, 0.25, -2.33, 0.77, +-R_ARC_TO, 3.95, 3.95, 0, 0, 0, -1.42, 1.94, +-LINE_TO, 2.21, 3.66, +-R_ARC_TO, 6.79, 6.79, 0, 0, 1, 2.27, -1.94, +-CUBIC_TO, 5.4, 1.22, 6.4, 0.98, 7.5, 0.98, +-R_CUBIC_TO, 1.1, 0, 2.08, 0.24, 2.99, 0.72, +-ARC_TO, 6.66, 6.66, 0, 0, 1, 12.76, 3.6, +-H_LINE_TO, 7.51, +-R_LINE_TO, -0.01, 0.01, ++ ++MOVE_TO, 8, 15.5, ++H_LINE_TO, 14, ++V_LINE_TO, 23.5, ++H_LINE_TO, 8, + CLOSE, +-R_MOVE_TO, 6.01, 1.31, +-R_CUBIC_TO, 0.19, 0.4, 0.32, 0.83, 0.41, 1.27, +-R_CUBIC_TO, 0.09, 0.44, 0.15, 0.89, 0.15, 1.36, +-R_CUBIC_TO, 0, 1.7, -0.55, 3.16, -1.68, 4.38, +-R_CUBIC_TO, -1.11, 1.23, -2.47, 1.93, -4.1, 2.13, +-R_LINE_TO, 2.63, -4.55, +-R_CUBIC_TO, 0.17, -0.28, 0.29, -0.59, 0.38, -0.92, +-R_CUBIC_TO, 0.09, -0.34, 0.15, -0.69, 0.15, -1.05, +-R_CUBIC_TO, 0, -0.52, -0.09, -0.99, -0.28, -1.42, +-R_ARC_TO, 3.96, 3.96, 0, 0, 0, -0.74, -1.2, +-R_H_LINE_TO, 3.08, +-R_V_LINE_TO, 0.01, +-CLOSE ++ ++MOVE_TO, 8, 23.5, ++H_LINE_TO, 23, ++V_LINE_TO, 31.5, ++H_LINE_TO, 8, ++CLOSE +\ No newline at end of file +diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc +index 6d2ea1d68430b..406d9402d41e1 100644 +--- a/components/search/ntp_features.cc ++++ b/components/search/ntp_features.cc +@@ -98,7 +98,7 @@ BASE_FEATURE(kNtpDummyModules, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, Google Drive module will be shown. + // This is a kill switch. Keep indefinitely. +-BASE_FEATURE(kNtpDriveModule, base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpDriveModule, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, the NTP Drive module does not require sync. + BASE_FEATURE(kNtpDriveModuleHistorySyncRequirement, +@@ -121,7 +121,7 @@ BASE_FEATURE(kNtpMiddleSlotPromo, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, middle slot promo will be dismissed from New Tab Page until new + // promo message is populated +-BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_ENABLED_BY_DEFAULT); + + // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". + // This is used for an emergency Finch param. Keep indefinitely. +diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h +index d8c168edc6c92..2d8243d947b94 100644 +--- a/ui/native_theme/native_theme.h ++++ b/ui/native_theme/native_theme.h +@@ -602,7 +602,7 @@ class COMPONENT_EXPORT(NATIVE_THEME) NativeTheme { + std::optional user_color_; + std::optional scheme_variant_; + ColorProviderKey::UserColorSource preferred_color_source_ = +- ColorProviderKey::UserColorSource::kAccent; ++ ColorProviderKey::UserColorSource::kBaseline; + base::TimeDelta caret_blink_interval_; + + raw_ptr associated_web_instance_ = nullptr; +diff --git a/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn b/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn +index 8ad6296ea91dc..717abf4b71523 100644 +--- a/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn ++++ b/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn +@@ -91,7 +91,7 @@ if (is_chrome_branded) { + "google_g.svg", + "google_g_gradient.svg", + "google_g_cr23.svg", +- "google_logo.svg", ++ "openbrowser_logo_white.png", + "mic.svg", + ] + input_files_base_dir = +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.css b/ui/webui/resources/cr_components/searchbox/searchbox.css +index dc4fdb93e0fa3..5ca09ff564360 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox.css +@@ -12,7 +12,7 @@ + :host { + /* Embedders should define --cr-searchbox-min-width. */ + --cr-searchbox-width: var(--cr-searchbox-min-width); +- --cr-searchbox-border-radius: calc(0.5 * var(--cr-searchbox-height)); ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-icon-width: 26px; + --cr-searchbox-inner-icon-margin: 8px; + --cr-searchbox-voice-icon-offset: 16px; +@@ -274,11 +274,29 @@ cr-searchbox-icon { + } + + :host(:not([use-webkit-search-icons_])) #voiceSearchButton { +- background-image: url(//resources/cr_components/searchbox/icons/mic.svg); ++ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/mic.svg); ++ -webkit-mask-position: center; ++ -webkit-mask-repeat: no-repeat; ++ -webkit-mask-size: 21px 21px; + } + + :host(:not([use-webkit-search-icons_])) #lensSearchButton { +- background-image: url(//resources/cr_components/searchbox/icons/camera.svg); ++ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/camera.svg); ++ -webkit-mask-position: center; ++ -webkit-mask-repeat: no-repeat; ++ -webkit-mask-size: 21px 21px; ++} ++ ++/* White icons in dark mode */ ++:host(:not([use-webkit-search-icons_])[is-dark]) #voiceSearchButton, ++:host(:not([use-webkit-search-icons_])[is-dark]) #lensSearchButton { ++ background-color: white; ++} ++ ++/* Black icons in light mode */ ++:host(:not([use-webkit-search-icons_]):not([is-dark])) #voiceSearchButton, ++:host(:not([use-webkit-search-icons_]):not([is-dark])) #lensSearchButton { ++ background-color: black; + } + + :host([use-webkit-search-icons_]) #voiceSearchButton { +@@ -373,7 +391,7 @@ search-animated-glow { + } + + :host([ntp-realbox-next-enabled]) { +- --cr-searchbox-border-radius: 26px; ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-dropdown-padding-bottom: 12px; + /* Cannot touch this searchbox icon size var; + it's used by the rainbow outline AI button class in +@@ -540,7 +558,7 @@ search-animated-glow { + } + + :host([searchbox-layout-mode='Compact']) { +- --cr-searchbox-border-radius: 30px; ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-dropdown-padding-bottom: 10px; + --cr-searchbox-dropdown-padding-top: 10px; + --cr-searchbox-height: 56px; +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_match.css b/ui/webui/resources/cr_components/searchbox/searchbox_match.css +index 514d780649bba..48fe44b9e8788 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox_match.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox_match.css +@@ -221,13 +221,14 @@ + + .match { + font-weight: var(--cr-searchbox-match-font-weight, 600); ++ color: var(--color-searchbox-results-foreground); + } + + /* In the lens side panel searchbox, the typed prefix of the match should + * have a different color than the rest of the autocomplete suggestion. */ + :host(:not([is-top-chrome-searchbox_])) #contents span:not(.match), + #ellipsis { +- color: var(--color-searchbox-results-typed-prefix, --color-searchbox-results-foreground); ++ color: var(--color-searchbox-results-foreground); + } + + /* Used to override contents color in zero prefix matches */ +diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +index 735615a4ba785..d95689b8b1196 100644 +--- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts ++++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +@@ -15,7 +15,8 @@ export function getHtml(this: CrDrawerElement) { + + + ++ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, ++ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> + + + ++ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, ++ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> + + + + + + +- Chromium ++ OpenBrowser + + +- Chromium ++ OpenBrowser + + + + +- ++ + +- ++ + +- ++ + + +- Chromium is a web browser that runs webpages and applications with lightning speed. It's fast, stable, and easy to use. Browse the web more safely with malware and phishing protection built into Chromium. ++ OpenBrowser is a web browser that runs webpages and applications with lightning speed. It's fast, stable, and easy to use. Browse the web more safely with malware and phishing protection built into OpenBrowser. + + +- Welcome to Chromium; new browser window opened ++ Welcome to OpenBrowser; new browser window opened + + + + +- Welcome to Chromium ++ Welcome to OpenBrowser + + + + +- ChromiumOS ++ OpenBrowserOS + + +- ChromiumOS ++ OpenBrowserOS + + +- ChromiumOS ++ OpenBrowserOS + + +- +- Chromium Enterprise logo ++ ++ OpenBrowser Enterprise logo + + + +@@ -346,7 +346,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- Task Manager - Chromium ++ Task Manager - OpenBrowser + + + +@@ -380,12 +380,12 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + All tasks + + +- Help make Chromium better by sending crash reports and $1usage statistics to Google ++ Help make OpenBrowser better by sending crash reports and $1usage statistics to Google + + + This action will: + <br><br> +- • Reset some Chromium settings and Chromium shortcuts ++ • Reset some OpenBrowser settings and OpenBrowser shortcuts + <br> + • Disable extensions + <br> +@@ -403,7 +403,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- $1Google - Chromium ++ $1Google - OpenBrowser + + + +@@ -411,19 +411,19 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- Chromium - $1Google ++ OpenBrowser - $1Google + + + + + +- $1Google - Network Sign-in - Chromium ++ $1Google - Network Sign-in - OpenBrowser + + + + + +- Chromium - Network Sign-in - $1Google ++ OpenBrowser - Network Sign-in - $1Google + + + +@@ -442,18 +442,18 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- $1Google - Chromium ++ $1Google - OpenBrowser + + + + +- $1Google - Chromium Beta ++ $1Google - OpenBrowser Beta + + +- $1Google - Chromium Dev ++ $1Google - OpenBrowser Dev + + +- $1Google - Chromium Canary ++ $1Google - OpenBrowser Canary + + + +@@ -466,22 +466,22 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- The Chromium Authors ++ The OpenBrowser Authors + + +- Copyright {0,date,y}2016 The Chromium Authors. All rights reserved. ++ Copyright {0,date,y}2016 The OpenBrowser Authors. All rights reserved. + + + + +- +- ChromiumOS is made possible by additional <a target="_blank" href="$1">open source software</a>. ++ ++ OpenBrowserOS is made possible by additional <a target="_blank" href="$1">open source software</a>. + +- +- ChromiumOS is made possible by additional <a target="_blank" href="$1">open source software</a>, as is <a target="_blank" href="$2">Linux development environment</a>. ++ ++ OpenBrowserOS is made possible by additional <a target="_blank" href="$1">open source software</a>, as is <a target="_blank" href="$2">Linux development environment</a>. + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + + +@@ -492,108 +492,108 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> + + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + + + + +- To get future Chromium updates, you'll need macOS 12 or later. This computer is using macOS 11. ++ To get future OpenBrowser updates, you'll need macOS 12 or later. This computer is using macOS 11. + + + + +- Chromium may not function correctly because it is no longer supported on Windows XP or Windows Vista ++ OpenBrowser may not function correctly because it is no longer supported on Windows XP or Windows Vista + + + + +- To get future Chromium updates, you'll need Windows 10 or later. This computer is using Windows 7. ++ To get future OpenBrowser updates, you'll need Windows 10 or later. This computer is using Windows 7. + + + + +- To get future Chromium updates, you'll need Windows 10 or later. This computer is using Windows 8. ++ To get future OpenBrowser updates, you'll need Windows 10 or later. This computer is using Windows 8. + + + + +- To get future Chromium updates, you'll need Windows 10 or later. This computer is using Windows 8.1. ++ To get future OpenBrowser updates, you'll need Windows 10 or later. This computer is using Windows 8.1. + + + + +- Chromium may not function correctly because it is no longer supported on this Linux distribution ++ OpenBrowser may not function correctly because it is no longer supported on this Linux distribution + + + +- Chromium ++ OpenBrowser + + + + +- Chromium is unresponsive. Relaunch now? ++ OpenBrowser is unresponsive. Relaunch now? + + + + +- To send a number from here to your Android phone, sign in to Chromium on both devices. ++ To send a number from here to your Android phone, sign in to OpenBrowser on both devices. + + +- To send a number from $1www.google.com to your Android phone, sign in to Chromium on both devices. ++ To send a number from $1www.google.com to your Android phone, sign in to OpenBrowser on both devices. + + +- Make sure you are signed in to Chromium on your $1Pixel XL and then try sending again. ++ Make sure you are signed in to OpenBrowser on your $1Pixel XL and then try sending again. + + + + +- Please close all Chromium windows and try again. ++ Please close all OpenBrowser windows and try again. + + +- Are you sure you want to uninstall Chromium? ++ Are you sure you want to uninstall OpenBrowser? + +- +- Uninstall Chromium ++ ++ Uninstall OpenBrowser + + + +- Make Chromium the default browser ++ Make OpenBrowser the default browser + + + +- Let Chromium Run in the Background ++ Let OpenBrowser Run in the Background + + + + +- Let Chromium run in the background ++ Let OpenBrowser run in the background + + + + +- Disable Chromium Running in Background for Apps ++ Disable OpenBrowser Running in Background for Apps + + + + +- Disable Chromium running in background for apps ++ Disable OpenBrowser running in background for apps + + + +-Chromium cannot read and write to its data directory: ++OpenBrowser cannot read and write to its data directory: + + $1C:\Documents and Settings\devint\Local Settings\Application Data\Google\Chrome + + + +- Optional: Help improve ChromiumOS features and performance by automatically sending diagnostic and usage data to Google. ++ Optional: Help improve OpenBrowserOS features and performance by automatically sending diagnostic and usage data to Google. + + + +-Your profile can not be used because it is from a newer version of Chromium. ++Your profile can not be used because it is from a newer version of OpenBrowser. + +-Some features may be unavailable. Please specify a different profile directory or use a newer version of Chromium. ++Some features may be unavailable. Please specify a different profile directory or use a newer version of OpenBrowser. + + + Your preferences can not be read. +@@ -603,21 +603,21 @@ Some features may be unavailable and changes to preferences won't be saved. + + Your preferences file is corrupt or invalid. + +-Chromium is unable to recover your settings. ++OpenBrowser is unable to recover your settings. + + + + +- Open $1https://www.example-url.com/ in a new tab in Chromium. ++ Open $1https://www.example-url.com/ in a new tab in OpenBrowser. + + + + + +- Chromium lets you know if your passwords are ever compromised ++ OpenBrowser lets you know if your passwords are ever compromised + + +- Chromium ++ OpenBrowser + + + Password Manager +@@ -630,81 +630,81 @@ Chromium is unable to recover your settings. + + + +- Chromium is trying to $1show passwords ++ OpenBrowser is trying to $1show passwords + + + + +- Chromium is trying to show passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to show passwords. Type your Windows password to allow this. + + +- Chromium is trying to copy passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to copy passwords. Type your Windows password to allow this. + + +- Chromium is trying to edit passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to edit passwords. Type your Windows password to allow this. + + +- Chromium wants to export your passwords. Type your Windows password to allow this. ++ OpenBrowser wants to export your passwords. Type your Windows password to allow this. + + +- Chromium wants to delete your Password Manager data. Type your Windows password to allow this. ++ OpenBrowser wants to delete your Password Manager data. Type your Windows password to allow this. + + +- Chromium is trying to replace existing passwords. Type your Windows password to allow this. ++ OpenBrowser is trying to replace existing passwords. Type your Windows password to allow this. + + +- This computer already has a more recent version of Chromium. If the software is not working, please uninstall Chromium and try again. ++ This computer already has a more recent version of OpenBrowser. If the software is not working, please uninstall OpenBrowser and try again. + + +- Installation failed due to unspecified error. If Chromium is currently running, please close it and try again. ++ Installation failed due to unspecified error. If OpenBrowser is currently running, please close it and try again. + + +- Can not install the same Chromium version that is currently running. Please close Chromium and try again. ++ Can not install the same OpenBrowser version that is currently running. Please close OpenBrowser and try again. + + +- Chromium requires Windows 10 or higher. ++ OpenBrowser requires Windows 10 or higher. + + +- An operating system error occurred during installation. Please download Chromium again. ++ An operating system error occurred during installation. Please download OpenBrowser again. + + +- Another operation on Chromium is in progress. Please try again later. ++ Another operation on OpenBrowser is in progress. Please try again later. + + + The installer couldn't create a temporary directory. Please check for free disk space and permission to install software. + + +- The installer failed to uncompress archive. Please download Chromium again. ++ The installer failed to uncompress archive. Please download OpenBrowser again. + + +- The installer archive is corrupted or invalid. Please download Chromium again. ++ The installer archive is corrupted or invalid. Please download OpenBrowser again. + + + You do not have appropriate rights for system-level install. Try running the installer again as Administrator. + + +- Chromium is already installed for all users on your computer. ++ OpenBrowser is already installed for all users on your computer. + + +- Provides elevated privileges for $1Chromium. ++ Provides elevated privileges for $1OpenBrowser. + + +- Provides system tracing services for $1Chromium. If this service is disabled, performance traces created by the browser will not include system-wide events such as context switch and ready thread events. ++ Provides system tracing services for $1OpenBrowser. If this service is disabled, performance traces created by the browser will not include system-wide events such as context switch and ready thread events. + + + + +- Import Passwords To Chromium ++ Import Passwords To OpenBrowser + + +- Export Passwords From Chromium ++ Export Passwords From OpenBrowser + + + + +- ++ + Access the Internet + + +@@ -713,252 +713,252 @@ Chromium is unable to recover your settings. + + Uninstall + +- +- Pin Chromium to your taskbar to get to it quickly anytime ++ ++ Pin OpenBrowser to your taskbar to get to it quickly anytime + +- +- Pin Chromium ++ ++ Pin OpenBrowser + + + +- +- Keep Chromium in your Dock to get to it quickly anytime ++ ++ Keep OpenBrowser in your Dock to get to it quickly anytime + +- ++ + Keep in Dock + + +- +- Chromium isn't your default browser ++ ++ OpenBrowser isn't your default browser + +- +- Set Chromium as your default browser and pin it to your taskbar ++ ++ Set OpenBrowser as your default browser and pin it to your taskbar + + +- +- Set Chromium as your default PDF viewer ++ ++ Set OpenBrowser as your default PDF viewer + + + + +- Extensions, apps, and themes from unknown sources can harm your device. Chromium recommends only installing them from the $1Chrome Web Store ++ Extensions, apps, and themes from unknown sources can harm your device. OpenBrowser recommends only installing them from the $1Chrome Web Store + + +- Learn why Chromium blocks some downloads ++ desc="Text for the link to the help page about why OpenBrowser blocks some downloaded files."> ++ Learn why OpenBrowser blocks some downloads + + +- This file may be dangerous$1Chromium can check this download for you if you provide the password. Info about the file gets sent to Google Safe Browsing, but the file content and password stay on your device. ++ This file may be dangerous$1OpenBrowser can check this download for you if you provide the password. Info about the file gets sent to Google Safe Browsing, but the file content and password stay on your device. + + + + +- Adding to Chromium... ++ Adding to OpenBrowser... + + + +- $1bla.exe may be dangerous, so Chromium has blocked it. ++ $1bla.exe may be dangerous, so OpenBrowser has blocked it. + + + +- This file is dangerous, so Chromium has blocked it. ++ This file is dangerous, so OpenBrowser has blocked it. + + +- $1malware.exe is dangerous, so Chromium has blocked it. ++ $1malware.exe is dangerous, so OpenBrowser has blocked it. + + +- Chromium recommends scanning this file because it may be dangerous. ++ OpenBrowser recommends scanning this file because it may be dangerous. + + + + +- Chromium blocked this download because the file type isn't commonly downloaded and it may be dangerous ++ OpenBrowser blocked this download because the file type isn't commonly downloaded and it may be dangerous + + +- Chromium blocked this download because the file is dangerous ++ OpenBrowser blocked this download because the file is dangerous + + +- Chromium blocked this download because the file can harm your personal and social network accounts ++ OpenBrowser blocked this download because the file can harm your personal and social network accounts + + +- Chromium blocked this download because the file isn't commonly downloaded and it may be dangerous ++ OpenBrowser blocked this download because the file isn't commonly downloaded and it may be dangerous + + +- Chromium blocked this download because the archive file includes other files that may hide malware ++ OpenBrowser blocked this download because the archive file includes other files that may hide malware + + +- Chromium blocked this download because the file is deceptive and may make unexpected changes to your device ++ OpenBrowser blocked this download because the file is deceptive and may make unexpected changes to your device + + +- Chromium blocked this download because the site isn't using a secure connection and the file may have been tampered with ++ OpenBrowser blocked this download because the site isn't using a secure connection and the file may have been tampered with + + +- Chromium blocked this download because you turned Safe Browsing off and the file can't be verified ++ OpenBrowser blocked this download because you turned Safe Browsing off and the file can't be verified + + + + +- Learn why Chromium blocks some files ++ Learn why OpenBrowser blocks some files + + +- Learn why Chromium blocks some files, opens in new tab ++ Learn why OpenBrowser blocks some files, opens in new tab + + + + + +- Exit Chromium anyway? ++ Exit OpenBrowser anyway? + + + + +- Quit Chromium anyway? ++ Quit OpenBrowser anyway? + + + + + + +- Chromium is in background mode. ++ OpenBrowser is in background mode. + + + + + +- Google API keys are missing. Some functionality of Chromium will be disabled. ++ Google API keys are missing. Some functionality of OpenBrowser will be disabled. + + + + + +- $1Gmail Checker has been added to Chromium ++ $1Gmail Checker has been added to OpenBrowser + + + + +- Also delete data from Chromium ($1www.google.com) ++ Also delete data from OpenBrowser ($1www.google.com) + + + + +- Chromium found that "$1Gmail Checker" contains malware ++ OpenBrowser found that "$1Gmail Checker" contains malware + + +- Chromium found that these items contain malware: ++ OpenBrowser found that these items contain malware: + + + + +- This extension is no longer supported. Chromium recommends that you remove it instead. ++ This extension is no longer supported. OpenBrowser recommends that you remove it instead. + + + {NUM_EXTENSIONS, plural, +- =1 {This extension is no longer supported. Chromium recommends that you remove it.} +- other {These extensions are no longer supported. Chromium recommends that you remove them.}} ++ =1 {This extension is no longer supported. OpenBrowser recommends that you remove it.} ++ other {These extensions are no longer supported. OpenBrowser recommends that you remove them.}} + + +- Chromium recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a> ++ OpenBrowser recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a> + + + {NUM_EXTENSIONS, plural, +- =1 {Chromium recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} +- other {Chromium recommends that you remove them. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} ++ =1 {OpenBrowser recommends that you remove it. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} ++ other {OpenBrowser recommends that you remove them. <a href="$1" aria-description="$2" target="_blank">Learn more about supported extensions</a>} + } + + +- Remove $1Google Translate from Chromium ++ Remove $1Google Translate from OpenBrowser + + + + + +- This extension contains malware and is unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including your personal info. ++ This extension contains malware and is unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including your personal info. + + +- This extension violates the Chrome Web Store policy, and might be unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including your personal info. ++ This extension violates the Chrome Web Store policy, and might be unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including your personal info. + + +- This extension was unpublished by its developer, and might be unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including your personal info. ++ This extension was unpublished by its developer, and might be unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including your personal info. + + +- Chromium recommends you review this extension ++ OpenBrowser recommends you review this extension + + +- Chromium can't verify where this extension comes from, and it might be unsafe. Remove it from Chromium so it can no longer see and change your data on sites you visit, including personal info. ++ OpenBrowser can't verify where this extension comes from, and it might be unsafe. Remove it from OpenBrowser so it can no longer see and change your data on sites you visit, including personal info. + + +- On • Chromium can't verify where this extension comes from ++ On • OpenBrowser can't verify where this extension comes from + + +- Off • Chromium can't verify where this extension comes from ++ Off • OpenBrowser can't verify where this extension comes from + + +- This extension hasn't published privacy practices, such as how it collects and uses data. Chromium recommends that you remove it. ++ This extension hasn't published privacy practices, such as how it collects and uses data. OpenBrowser recommends that you remove it. + + + + + {NUM_EXTENSIONS, plural, +- =1 {Chromium recommends that you remove it} +- other {Chromium recommends that you remove them}} ++ =1 {OpenBrowser recommends that you remove it} ++ other {OpenBrowser recommends that you remove them}} + + +- Allow extension to show access requests in the Chromium toolbar ++ Allow extension to show access requests in the OpenBrowser toolbar + +- +- Warning: Chromium cannot prevent extensions from recording your browsing history. To disable this extension in Incognito mode, unselect this option. ++ ++ Warning: OpenBrowser cannot prevent extensions from recording your browsing history. To disable this extension in Incognito mode, unselect this option. + + +- Remove from Chromium ++ Remove from OpenBrowser + + +- In Chromium ++ In OpenBrowser + + +- Changes to this setting will be applied once Chromium restarts. ++ Changes to this setting will be applied once OpenBrowser restarts. + + + + +- To make Chromium safer, we disabled some extensions that aren't listed in the $1Chrome Web Store and may have been added without your knowledge. ++ To make OpenBrowser safer, we disabled some extensions that aren't listed in the $1Chrome Web Store and may have been added without your knowledge. + + +- To make Chromium safer, we disabled the following extension that isn't listed in the $1Chrome Web Store and may have been added without your knowledge. ++ To make OpenBrowser safer, we disabled the following extension that isn't listed in the $1Chrome Web Store and may have been added without your knowledge. + + + + + +- Customize and control Chromium ++ Customize and control OpenBrowser + + + +- Customize and control Chromium. Update is available. ++ Customize and control OpenBrowser. Update is available. + + + +- Customize and control Chromium. Something needs your attention - click for details. ++ Customize and control OpenBrowser. Something needs your attention - click for details. + + + +- &Open in Chromium ++ &Open in OpenBrowser + + + +@@ -970,12 +970,12 @@ Chromium is unable to recover your settings. + + + +- About &Chromium ++ About &OpenBrowser + + + + +- Relaunch to Update &Chromium ++ Relaunch to Update &OpenBrowser + + + +@@ -987,32 +987,32 @@ Chromium is unable to recover your settings. + + + +- About &Chromium ++ About &OpenBrowser + + + + +- Relaunch to update &Chromium ++ Relaunch to update &OpenBrowser + + + + +- About &Chromium ++ About &OpenBrowser + + +- Relaunch to update &ChromiumOS ++ Relaunch to update &OpenBrowserOS + + + + + +- Chromium ++ OpenBrowser + + +- Chromium Helper ++ OpenBrowser Helper + + +- Chromium Helper ++ OpenBrowser Helper + + + +@@ -1021,24 +1021,24 @@ Chromium is unable to recover your settings. + + + +- C&ustomize Your Chromium ++ C&ustomize Your OpenBrowser + + +- Other Chromium Profiles ++ Other OpenBrowser Profiles + + +- &Manage Chromium Profiles ++ &Manage OpenBrowser Profiles + + + + +- C&ustomize your Chromium ++ C&ustomize your OpenBrowser + + +- Other Chromium profiles ++ Other OpenBrowser profiles + + +- &Manage Chromium profiles ++ &Manage OpenBrowser profiles + + + +@@ -1050,33 +1050,33 @@ Chromium is unable to recover your settings. + + + +- Chromium ++ OpenBrowser + + + + +- Sync and personalize Chromium across your devices ++ Sync and personalize OpenBrowser across your devices + + + + + +- You were signed in to Chromium as $1foo@gmail.com. Please use the same account to sign in again. ++ You were signed in to OpenBrowser as $1foo@gmail.com. Please use the same account to sign in again. + + +- Someone previously signed in to Chromium on this computer as $1user@example.com. Please create a new Chromium user to keep your information separate. ++ Someone previously signed in to OpenBrowser on this computer as $1user@example.com. Please create a new OpenBrowser user to keep your information separate. + + + + + +- Continue where you left off: Chromium restored your tabs from your last session. You can turn this off in ++ Continue where you left off: OpenBrowser restored your tabs from your last session. You can turn this off in + + +- Continue where you left off: Chromium restores your tabs every time you restart. To turn this off, go to ++ Continue where you left off: OpenBrowser restores your tabs every time you restart. To turn this off, go to + + +- Continue where you left off: Chromium can restore your tabs every time you restart. To turn this on, go to ++ Continue where you left off: OpenBrowser can restore your tabs every time you restart. To turn this on, go to + + + Settings. +@@ -1085,28 +1085,28 @@ Chromium is unable to recover your settings. + Settings, opens in new tab. + + +- +- Your organization requires you to sign into Chromium ++ ++ Your organization requires you to sign into OpenBrowser + + + +- Link your Chromium data to this account? ++ Link your OpenBrowser data to this account? + + +- You are signing in with a managed account and giving its administrator control over your Chromium profile. Your Chromium data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. $2Learn more ++ You are signing in with a managed account and giving its administrator control over your OpenBrowser profile. Your OpenBrowser data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. $2Learn more + + +- You are signing in with a managed account and giving its administrator control over your Chromium profile. Your Chromium data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. You can optionally create a new profile to keep your existing Chromium data separate. $2Learn more ++ You are signing in with a managed account and giving its administrator control over your OpenBrowser profile. Your OpenBrowser data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to $1pat@example.com. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. You can optionally create a new profile to keep your existing OpenBrowser data separate. $2Learn more + +- +- Your organization, $1manager.com, requires you to sign into Chromium ++ ++ Your organization, $1manager.com, requires you to sign into OpenBrowser + +- +- Sign in to Chromium? ++ ++ Sign in to OpenBrowser? + + + +- You're signed in to Chromium! ++ You're signed in to OpenBrowser! + + + You're signed in as $1foo@gmail.com. Now you can access your bookmarks, history, and other settings on all your signed in devices. +@@ -1115,40 +1115,40 @@ Chromium is unable to recover your settings. + + + +- Your organization manages Chromium ++ Your organization manages OpenBrowser + + +- $1The Company manages Chromium ++ $1The Company manages OpenBrowser + + +- Multiple organizations manage Chromium ++ Multiple organizations manage OpenBrowser + + + + +- To continue, sign in to Chromium as $1user@example.com. This makes sure that you've got your organization's policies. ++ To continue, sign in to OpenBrowser as $1user@example.com. This makes sure that you've got your organization's policies. + + + + + +- The extension "$1Screencast" wants you to sign in to Chromium ++ The extension "$1Screencast" wants you to sign in to OpenBrowser + + +- To use this extension as $1elisa.g.beckett@gmail.com, sign in to Chromium. ++ To use this extension as $1elisa.g.beckett@gmail.com, sign in to OpenBrowser. + + +- An extension wants you to sign in to Chromium ++ An extension wants you to sign in to OpenBrowser + + + + + + +- Your system administrator has configured Chromium to open an alternative browser to access $1example.com. ++ Your system administrator has configured OpenBrowser to open an alternative browser to access $1example.com. + + +- Your system administrator has configured Chromium to open $2Internet Explorer to access $1example.com. ++ Your system administrator has configured OpenBrowser to open $2Internet Explorer to access $1example.com. + + + +@@ -1160,21 +1160,21 @@ Chromium is unable to recover your settings. + + + +- +- Customize Chromium ++ ++ Customize OpenBrowser + + + + +- Make Chromium Yours ++ Make OpenBrowser Yours + + + +- +- Customize Chromium to give it a new look ++ ++ Customize OpenBrowser to give it a new look + +- +- Click the Customize Chromium button on the New Tab Page to give Chromium a new look ++ ++ Click the Customize OpenBrowser button on the New Tab Page to give OpenBrowser a new look + + + +@@ -1188,263 +1188,263 @@ Chromium is unable to recover your settings. + + + +- $1foo@gmail.com was previously using Chromium ++ $1foo@gmail.com was previously using OpenBrowser + + + + + + +- Sign in to Chromium? ++ desc="Text asking the user to sign into OpenBrowser while the OpenBrowser Signin Bubble intercept is shown."> ++ Sign in to OpenBrowser? + +- +- Make Chromium your own ++ ++ Make OpenBrowser your own + + +- Use Chromium without an account ++ desc="Label of the Decline button of the OpenBrowser Signin Bubble intercept that is shown when a signed out user signs in on the web with it's first account."> ++ Use OpenBrowser without an account + + + + +- Sign In to Chromium? ++ desc="Text asking the user to sign into OpenBrowser while the OpenBrowser Signin Bubble intercept is shown."> ++ Sign In to OpenBrowser? + +- +- Make Chromium Your Own ++ ++ Make OpenBrowser Your Own + + +- Use Chromium Without an Account ++ desc="Label of the Decline button of the OpenBrowser Signin Bubble intercept that is shown when a signed out user signs in on the web with it's first account."> ++ Use OpenBrowser Without an Account + + + + + +- Sign in to Chromium in a new profile? ++ Sign in to OpenBrowser in a new profile? + + +- Switch to existing Chromium profile? ++ Switch to existing OpenBrowser profile? + +- +- You're already signed in as $1foo@gmail.com in another Chromium profile ++ ++ You're already signed in as $1foo@gmail.com in another OpenBrowser profile + +- +- To stay safer online with your parent’s choices, switch to your Chromium profile where you’re already signed in as $1foo@gmail.com ++ ++ To stay safer online with your parent’s choices, switch to your OpenBrowser profile where you’re already signed in as $1foo@gmail.com + + +- $1Elisa is already signed in to this Chromium profile. To keep your browsing separate, Chromium can create your own profile for you. ++ $1Elisa is already signed in to this OpenBrowser profile. To keep your browsing separate, OpenBrowser can create your own profile for you. + + +- $1Elisa is already signed in. To keep your browsing separate, sign in to Chromium in your own profile as $2foo@gmail.com. ++ $1Elisa is already signed in. To keep your browsing separate, sign in to OpenBrowser in your own profile as $2foo@gmail.com. + +- +- To get your passwords and more on all your devices, sign in to Chromium ++ ++ To get your passwords and more on all your devices, sign in to OpenBrowser + +- +- To get your passwords, bookmarks, and more on all your devices, sign in to Chromium ++ ++ To get your passwords, bookmarks, and more on all your devices, sign in to OpenBrowser + +- +- To stay safer online with your parent’s choices, sign in to Chromium ++ ++ To stay safer online with your parent’s choices, sign in to OpenBrowser + +- +- While you're signed in, you can use your passwords and more from your Google Account in Chromium. To change this, go to “Your account in Chromium”. ++ ++ While you're signed in, you can use your passwords and more from your Google Account in OpenBrowser. To change this, go to “Your account in OpenBrowser”. + + +- While you're signed in, you can use your passwords and more from your Google Account in Chromium. $1CTRL+SHIFT+M can change your Google services settings. ++ While you're signed in, you can use your passwords and more from your Google Account in OpenBrowser. $1CTRL+SHIFT+M can change your Google services settings. + +- +- Sign out of Chromium? ++ ++ Sign out of OpenBrowser? + +- +- Your passwords, payment methods, and addresses that you saved in your Google Account will be removed from this device. To use them again in Chromium, sign back in. ++ ++ Your passwords, payment methods, and addresses that you saved in your Google Account will be removed from this device. To use them again in OpenBrowser, sign back in. + +- +- Your passwords and other Chromium data that you saved in your Google Account will be removed from this device. To use them again in Chromium, sign back in. ++ ++ Your passwords and other OpenBrowser data that you saved in your Google Account will be removed from this device. To use them again in OpenBrowser, sign back in. + +- ++ + {count, plural, +- =1 {Chromium needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data (1 item) will be deleted.} +- other {Chromium needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data ({count} items) will be deleted.}} ++ =1 {OpenBrowser needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data (1 item) will be deleted.} ++ other {OpenBrowser needs to verify it’s you before some data can be saved in your Google Account and used on all your devices. If you sign out now, this data ({count} items) will be deleted.}} + +- ++ + {count, plural, +- =1 {Some of your Chromium data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data (1 item) will be deleted.} +- other {Some of your Chromium data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data ({count} items) will be deleted.}} ++ =1 {Some of your OpenBrowser data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data (1 item) will be deleted.} ++ other {Some of your OpenBrowser data hasn't been saved in your Google Account yet. Try waiting a few minutes before signing out. If you sign out now, this data ({count} items) will be deleted.}} + + +- You’ll be signed out of most sites when you close all Chromium windows, except your Google Account if you’re signed in to Chromium. To let sites remember you, $1go to settings. ++ You’ll be signed out of most sites when you close all OpenBrowser windows, except your Google Account if you’re signed in to OpenBrowser. To let sites remember you, $1go to settings. + + +- If you forgot your passphrase or want to change this setting, $1clear the Chromium data in your account ++ If you forgot your passphrase or want to change this setting, $1clear the OpenBrowser data in your account + + +- Clear the Chromium data in your account ++ Clear the OpenBrowser data in your account + + +- Your data is encrypted with your passphrase. Enter it to use and save Chromium data in your Google Account. ++ Your data is encrypted with your passphrase. Enter it to use and save OpenBrowser data in your Google Account. + + +- Click to close the Chromium sign-in dialog ++ desc="Accessibility label (read by the accessibility tools) of the avatar button when the OpenBrowser Signin bubble is shown. The text implies that the expanded bubble underneath the button is closable by clicking on the button. The actual text is 'Sign in to OpenBrowser?' with a bubble shown under it."> ++ Click to close the OpenBrowser sign-in dialog + + +- Chromium account requires re-authentication ++ desc="Accessibility label (read by the accessibility tools) of the avatar button when OpenBrowser is in 'Sign-in pending' state. This state means that the account associated with OpenBrowser does not have valid credentials anymore and needs to be re-authenticated."> ++ OpenBrowser account requires re-authentication + + + +- +- To get your passwords and more on all your devices, sign in to Chromium. This password will be saved in your Google Account after you sign in. ++ ++ To get your passwords and more on all your devices, sign in to OpenBrowser. This password will be saved in your Google Account after you sign in. + +- +- To get your addresses and more on all your devices, sign in to Chromium. This address will be saved in your Google Account after you sign in. ++ ++ To get your addresses and more on all your devices, sign in to OpenBrowser. This address will be saved in your Google Account after you sign in. + + + + + + +- Customize your new Chromium profile ++ Customize your new OpenBrowser profile + + +- Customize your Chromium profile ++ Customize your OpenBrowser profile + + + + + +- +- ChromiumOS System ++ ++ OpenBrowserOS System + + +- ChromiumOS could not sync your data because your account sign-in details are out of date. ++ OpenBrowserOS could not sync your data because your account sign-in details are out of date. + + +- ChromiumOS could not sync your data because Sync is not available for your domain. ++ OpenBrowserOS could not sync your data because Sync is not available for your domain. + + +- ChromiumOS could not sync your data due to an error signing in. ++ OpenBrowserOS could not sync your data due to an error signing in. + + + + + +- Sign in to Chromium ++ Sign in to OpenBrowser + + +- Your Chromium ++ Your OpenBrowser + + +- +- Remove account from Chromium ++ ++ Remove account from OpenBrowser + +- +- Other Chromium profiles ++ ++ Other OpenBrowser profiles + +- +- Manage Chromium profiles ++ ++ Manage OpenBrowser profiles + + +- Sign out of Chromium ++ desc="The text label of the Sign out of OpenBrowser button in the Profile Menu."> ++ Sign out of OpenBrowser + + +- Add Chromium profile ++ Add OpenBrowser profile + + + +- +- Remove Account from Chromium ++ ++ Remove Account from OpenBrowser + +- +- Other Chromium Profiles ++ ++ Other OpenBrowser Profiles + +- +- Manage Chromium Profiles ++ ++ Manage OpenBrowser Profiles + + +- Sign Out of Chromium ++ desc="The text label of the Sign out of OpenBrowser button in the Profile Menu."> ++ Sign Out of OpenBrowser + + +- Add Chromium Profile ++ Add OpenBrowser Profile + + + + + + +- Remove from Chromium... ++ Remove from OpenBrowser... + + + + +- Remove this app's data from Chromium ++ Remove this app's data from OpenBrowser + + + +- +- Chromium Apps ++ ++ OpenBrowser Apps + + +- Chromium Apps ++ OpenBrowser Apps + + +- ++ + +- ++ + + + + + + +- $1example.com requires that you read and accept the following Terms of Service before using this device. These terms do not expand, modify or limit the ChromiumOS Terms. ++ $1example.com requires that you read and accept the following Terms of Service before using this device. These terms do not expand, modify or limit the OpenBrowserOS Terms. + + + + + +- Chromium is using your camera and microphone. ++ OpenBrowser is using your camera and microphone. + + +- Chromium is using your microphone. ++ OpenBrowser is using your microphone. + + +- Chromium is using your camera. ++ OpenBrowser is using your camera. + + + + + + {NUM_DEVICES, plural, +- =0 {1 HID device was being accessed by one or more Chromium extensions} +- =1 {1 HID device is being accessed by one or more Chromium extensions} +- other {# HID devices are being accessed by one or more Chromium extensions}} ++ =0 {1 HID device was being accessed by one or more OpenBrowser extensions} ++ =1 {1 HID device is being accessed by one or more OpenBrowser extensions} ++ other {# HID devices are being accessed by one or more OpenBrowser extensions}} + + + + + {NUM_DEVICES, plural, +- =0 {1 USB device was being accessed by one or more Chromium extensions} +- =1 {1 USB device is being accessed by one or more Chromium extensions} +- other {# USB devices are being accessed by one or more Chromium extensions}} ++ =0 {1 USB device was being accessed by one or more OpenBrowser extensions} ++ =1 {1 USB device is being accessed by one or more OpenBrowser extensions} ++ other {# USB devices are being accessed by one or more OpenBrowser extensions}} + + + + + + +- The profile appears to be in use by another Chromium process ($112345) on another computer ($2example.com). Chromium has locked the profile so that it doesn't get corrupted. If you are sure no other processes are using this profile, you can unlock the profile and relaunch Chromium. ++ The profile appears to be in use by another OpenBrowser process ($112345) on another computer ($2example.com). OpenBrowser has locked the profile so that it doesn't get corrupted. If you are sure no other processes are using this profile, you can unlock the profile and relaunch OpenBrowser. + + + + + + +- Set Chromium as your default browser ++ Set OpenBrowser as your default browser + + + +@@ -1452,40 +1452,40 @@ Chromium is unable to recover your settings. + + + +- This person's browsing data will be deleted from this device. To recover the data, sign in to Chromium as $2foo@example.com. ++ This person's browsing data will be deleted from this device. To recover the data, sign in to OpenBrowser as $2foo@example.com. + + + + +- Chromium just got better ++ OpenBrowser just got better + + +- Now it's easier to use Chromium with your Google Account and on shared computers. ++ Now it's easier to use OpenBrowser with your Google Account and on shared computers. + + +- This is your Chromium ++ This is your OpenBrowser + + +- Your web, bookmarks, and other Chromium stuff live here. ++ Your web, bookmarks, and other OpenBrowser stuff live here. + + +- Guests can use Chromium without leaving anything behind. ++ Guests can use OpenBrowser without leaving anything behind. + + +- If you share a computer, friends and family can browse separately and set up Chromium just the way they want. ++ If you share a computer, friends and family can browse separately and set up OpenBrowser just the way they want. + + +- Click your name to open Chromium and start browsing. ++ Click your name to open OpenBrowser and start browsing. + + +- Add yourself to Chromium ++ Add yourself to OpenBrowser + + + + + + +- Click the Chromium menu ++ Click the OpenBrowser menu + + + Click “Password Manager” +@@ -1500,82 +1500,82 @@ Chromium is unable to recover your settings. + + + +- ''' It also controls what page is shown when you start Chromium. ''' ++ ''' It also controls what page is shown when you start OpenBrowser. ''' + + +- ''' It also controls what page is shown when you start Chromium or search from the Omnibox. ''' ++ ''' It also controls what page is shown when you start OpenBrowser or search from the Omnibox. ''' + + + + +- Discover great apps, games, extensions and themes for Chromium. ++ Discover great apps, games, extensions and themes for OpenBrowser. + + + + + +- Chromium (mDNS-In) ++ OpenBrowser (mDNS-In) + +- ++ + +- ++ + +- ++ + + +- Inbound rule for Chromium to allow mDNS traffic. ++ Inbound rule for OpenBrowser to allow mDNS traffic. + +- ++ + +- ++ + +- ++ + + + + +- +- If an image doesn’t have a useful description, Chromium will try to provide one for you. To create descriptions, images are sent to Google. You can turn this off in settings at any time. ++ ++ If an image doesn’t have a useful description, OpenBrowser will try to provide one for you. To create descriptions, images are sent to Google. You can turn this off in settings at any time. + +- +- If an image doesn’t have a useful description, Chromium will try to provide one for you. To create descriptions, images are sent to Google. ++ ++ If an image doesn’t have a useful description, OpenBrowser will try to provide one for you. To create descriptions, images are sent to Google. + + + This uses the same spell checker that's used in Google search. Text you type in the browser is sent to Google. You can always change this behavior in settings. + + + +- Open link in new Chromium &tab ++ Open link in new OpenBrowser &tab + + +- Open link in Chromium inco&gnito window ++ Open link in OpenBrowser inco&gnito window + + + + +- Open Link in New Chromium &tab ++ Open Link in New OpenBrowser &tab + + +- Open Link in Chromium Inco&gnito Window ++ Open Link in OpenBrowser Inco&gnito Window + + + + + +- Making Chromium yours... ++ Making OpenBrowser yours... + + + + + + +- Relaunch Chromium ++ Relaunch OpenBrowser + + + {COUNT, plural, +- =0 {A new update for Chromium is available and will be applied as soon as you relaunch.} +- =1 {A new update for Chromium is available and will be applied as soon as you relaunch. Your Incognito window won't reopen.} +- other {A new update for Chromium is available and will be applied as soon as you relaunch. Your # Incognito windows won't reopen.}} ++ =0 {A new update for OpenBrowser is available and will be applied as soon as you relaunch.} ++ =1 {A new update for OpenBrowser is available and will be applied as soon as you relaunch. Your Incognito window won't reopen.} ++ other {A new update for OpenBrowser is available and will be applied as soon as you relaunch. Your # Incognito windows won't reopen.}} + + + Relaunch +@@ -1583,10 +1583,10 @@ Chromium is unable to recover your settings. + + + +- Restart ChromiumOS ++ Restart OpenBrowserOS + + +- ChromiumOS needs to be restarted to apply the update. ++ OpenBrowserOS needs to be restarted to apply the update. + + + Restart +@@ -1595,71 +1595,71 @@ Chromium is unable to recover your settings. + + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + +- Not used in Chromium. Placeholder to keep resource maps in sync. ++ Not used in OpenBrowser. Placeholder to keep resource maps in sync. + + + + + +- Reinstall Chromium ++ Reinstall OpenBrowser + + + +- Chromium is Out of Date ++ OpenBrowser is Out of Date + + + + +- Chromium is out of date ++ OpenBrowser is out of date + + + +- Can't update Chromium ++ Can't update OpenBrowser + + +- Chromium couldn't update to the latest version, so you're missing out on new features and security fixes. ++ OpenBrowser couldn't update to the latest version, so you're missing out on new features and security fixes. + + + + +- Update Chromium ++ Update OpenBrowser + + +- Enter your passphrase to use and save Chromium data in your account, $1elisa.beckett@gmail.com ++ Enter your passphrase to use and save OpenBrowser data in your account, $1elisa.beckett@gmail.com + + +- Verify it's you to use and save Chromium data in your account, $1elisa.beckett@gmail.com ++ Verify it's you to use and save OpenBrowser data in your account, $1elisa.beckett@gmail.com + + +- To use and save Chromium data in your Google Account, update Chromium ++ To use and save OpenBrowser data in your Google Account, update OpenBrowser + + +- Update Chromium to keeping using the Chromium data in your Google Account, $1elisa.beckett@gmail.com ++ Update OpenBrowser to keeping using the OpenBrowser data in your Google Account, $1elisa.beckett@gmail.com + + + + +- Update Chromium to start sync ++ Update OpenBrowser to start sync + + +- Update Chromium ++ Update OpenBrowser + + + + +- Chromium is out of date ++ OpenBrowser is out of date + + + +- Update Chromium ++ Update OpenBrowser + + + + +- Update Chromium ++ Update OpenBrowser + + + +@@ -1667,92 +1667,92 @@ Chromium is unable to recover your settings. + + + +- +- Chromium will restart in $11 minute, 7 seconds ++ ++ OpenBrowser will restart in $11 minute, 7 seconds + +- +- Please restart Chromium now ++ ++ Please restart OpenBrowser now + +- +- A special security update for Chromium was just applied. Restart now and we'll restore your tabs. ++ ++ A special security update for OpenBrowser was just applied. Restart now and we'll restore your tabs. + + + + +- Chromium Tab ++ OpenBrowser Tab + + +- To share your screen, allow screen recording for Chromium in System Settings ++ To share your screen, allow screen recording for OpenBrowser in System Settings + + +- To share your screen, allow screen recording for Chromium in System Settings. ++ To share your screen, allow screen recording for OpenBrowser in System Settings. + + +- To share your window, allow screen recording for Chromium in System Settings ++ To share your window, allow screen recording for OpenBrowser in System Settings + + +- To share your window, allow screen recording for Chromium in System Settings. ++ To share your window, allow screen recording for OpenBrowser in System Settings. + + +- You'll then need to restart Chromium. ++ You'll then need to restart OpenBrowser. + + +- To share system audio, open System Settings and allow 'System Audio Recording Only' for Chromium. You'll then need to restart Chromium. ++ To share system audio, open System Settings and allow 'System Audio Recording Only' for OpenBrowser. You'll then need to restart OpenBrowser. + + + + + +- Chromium needs permission to access your camera to create a 3D map of your surroundings ++ OpenBrowser needs permission to access your camera to create a 3D map of your surroundings + + +- Chromium needs permission to access your camera for this site ++ OpenBrowser needs permission to access your camera for this site + + +- Chromium needs permission to track your hands ++ OpenBrowser needs permission to track your hands + + +- Chromium needs permission to access your microphone for this site ++ OpenBrowser needs permission to access your microphone for this site + + +- Chromium needs permission to access your camera and microphone for this site ++ OpenBrowser needs permission to access your camera and microphone for this site + + +- Chromium needs access to your location to share your location with this site ++ OpenBrowser needs access to your location to share your location with this site + + +- Chromium needs storage access to download files ++ OpenBrowser needs storage access to download files + + + +- Chromium needs camera permission to create a 3D map of your surroundings ++ OpenBrowser needs camera permission to create a 3D map of your surroundings + + +- Chromium needs camera permission for this site ++ OpenBrowser needs camera permission for this site + + +- Chromium needs permission to track your hands ++ OpenBrowser needs permission to track your hands + + +- Chromium needs microphone permission for this site ++ OpenBrowser needs microphone permission for this site + + +- Chromium needs camera and microphone permissions for this site ++ OpenBrowser needs camera and microphone permissions for this site + + +- Chromium needs location permission for this site ++ OpenBrowser needs location permission for this site + + +- Chromium needs storage access permission to download files ++ OpenBrowser needs storage access permission to download files + + +- Chromium needs permission to map your surroundings and track your hands ++ OpenBrowser needs permission to map your surroundings and track your hands + + + + + +- Once Chromium has access, websites will be able to ask you for access. ++ Once OpenBrowser has access, websites will be able to ask you for access. + + + This will allow you to select from available devices and display content on them. +@@ -1761,12 +1761,12 @@ Chromium is unable to recover your settings. + + + +- Customize Chromium ++ Customize OpenBrowser + + + + +- Chromium history ++ OpenBrowser history + + + +@@ -2175,17 +2175,17 @@ Chromium is unable to recover your settings. + + + +- Please wait while Chromium installs the latest system updates. ++ Please wait while OpenBrowser installs the latest system updates. + + +- ChromiumOS terms ++ OpenBrowserOS terms + + + + + + +- Go to Chromium notification settings ++ Go to OpenBrowser notification settings + + + +@@ -2193,115 +2193,115 @@ Chromium is unable to recover your settings. + + + {0, plural, +- =0 {A Chromium update is available} +- =1 {A Chromium update is available} +- other {A Chromium update has been available for # days}} ++ =0 {A OpenBrowser update is available} ++ =1 {A OpenBrowser update is available} ++ other {A OpenBrowser update has been available for # days}} + + + {COUNT, plural, +- =0 {Your administrator asks that you relaunch Chromium to apply this update} +- =1 {Your administrator asks that you relaunch Chromium to apply this update. Your Incognito window won't reopen.} +- other {Your administrator asks that you relaunch Chromium to apply this update. Your # Incognito windows won't reopen.}} ++ =0 {Your administrator asks that you relaunch OpenBrowser to apply this update} ++ =1 {Your administrator asks that you relaunch OpenBrowser to apply this update. Your Incognito window won't reopen.} ++ other {Your administrator asks that you relaunch OpenBrowser to apply this update. Your # Incognito windows won't reopen.}} + + + {0, plural, +- =1 {Relaunch Chromium within a day} +- other {Relaunch Chromium within # days}} ++ =1 {Relaunch OpenBrowser within a day} ++ other {Relaunch OpenBrowser within # days}} + + + {0, plural, +- =1 {Chromium will relaunch in an hour} +- other {Chromium will relaunch in # hours}} ++ =1 {OpenBrowser will relaunch in an hour} ++ other {OpenBrowser will relaunch in # hours}} + + + {0, plural, +- =1 {Chromium will relaunch in 1 minute} +- other {Chromium will relaunch in # minutes}} ++ =1 {OpenBrowser will relaunch in 1 minute} ++ other {OpenBrowser will relaunch in # minutes}} + + + {0, plural, +- =0 {Chromium will relaunch now} +- =1 {Chromium will relaunch in 1 second} +- other {Chromium will relaunch in # seconds}} ++ =0 {OpenBrowser will relaunch now} ++ =1 {OpenBrowser will relaunch in 1 second} ++ other {OpenBrowser will relaunch in # seconds}} + + + {COUNT, plural, +- =0 {Your administrator requires that you relaunch Chromium to apply an update} +- =1 {Your administrator requires that you relaunch Chromium to apply an update. Your Incognito window won't reopen.} +- other {Your administrator requires that you relaunch Chromium to apply an update. Your # Incognito windows won't reopen.}} ++ =0 {Your administrator requires that you relaunch OpenBrowser to apply an update} ++ =1 {Your administrator requires that you relaunch OpenBrowser to apply an update. Your Incognito window won't reopen.} ++ other {Your administrator requires that you relaunch OpenBrowser to apply an update. Your # Incognito windows won't reopen.}} + + + {COUNT, plural, +- =0 {Advanced Protection requires that you relaunch Chromium to apply an update} +- =1 {Advanced Protection requires that you relaunch Chromium to apply an update. Your Incognito window won't reopen.} +- other {Advanced Protection requires that you relaunch Chromium to apply an update. Your # Incognito windows won't reopen.}} ++ =0 {Advanced Protection requires that you relaunch OpenBrowser to apply an update} ++ =1 {Advanced Protection requires that you relaunch OpenBrowser to apply an update. Your Incognito window won't reopen.} ++ other {Advanced Protection requires that you relaunch OpenBrowser to apply an update. Your # Incognito windows won't reopen.}} + + + +- ++ + +- +- Launching Chromium... ++ ++ Launching OpenBrowser... + +- +- Couldn't launch Chromium. Try again. ++ ++ Couldn't launch OpenBrowser. Try again. + +- +- Relaunch Chromium ++ ++ Relaunch OpenBrowser + + + +- Share a Chromium tab ++ Share a OpenBrowser tab + + + + +- Chromium was automatically closed ++ OpenBrowser was automatically closed + +- +- Your organization closes Chromium when it isn't used for $130 minutes. Browsing data was deleted. This could include history, autofill, and downloads. ++ ++ Your organization closes OpenBrowser when it isn't used for $130 minutes. Browsing data was deleted. This could include history, autofill, and downloads. + +- +- Your organization deletes Chromium data when it isn't used for $130 minutes. This could include history, autofill, and downloads. ++ ++ Your organization deletes OpenBrowser data when it isn't used for $130 minutes. This could include history, autofill, and downloads. + +- +- Your organization closes Chromium when it isn't used for $130 minutes. ++ ++ Your organization closes OpenBrowser when it isn't used for $130 minutes. + + + + + +- Chromium will soon close ++ OpenBrowser will soon close + + +- Chromium will soon delete browsing data ++ OpenBrowser will soon delete browsing data + + +- Chromium will soon close and delete data ++ OpenBrowser will soon close and delete data + +- ++ + {COUNT, plural, +- =1 {Your organization automatically closes Chromium when it isn't used for 1 minute.} +- other {Your organization automatically closes Chromium when it isn't used for # minutes.}} ++ =1 {Your organization automatically closes OpenBrowser when it isn't used for 1 minute.} ++ other {Your organization automatically closes OpenBrowser when it isn't used for # minutes.}} + +- ++ + {COUNT, plural, +- =1 {Your organization automatically deletes browsing data when Chromium isn't used for 1 minute. This could include history, autofill, and downloads. Your tabs will stay open.} +- other {Your organization automatically deletes browsing data when Chromium isn't used for # minutes. This could include history, autofill, and downloads. Your tabs will stay open.}} ++ =1 {Your organization automatically deletes browsing data when OpenBrowser isn't used for 1 minute. This could include history, autofill, and downloads. Your tabs will stay open.} ++ other {Your organization automatically deletes browsing data when OpenBrowser isn't used for # minutes. This could include history, autofill, and downloads. Your tabs will stay open.}} + +- ++ + {COUNT, plural, +- =1 {Your organization automatically closes Chromium when it isn't used for 1 minute. Browsing data is deleted. This could include history, autofill, and downloads.} +- other {Your organization automatically closes Chromium when it isn't used for # minutes. Browsing data is deleted. This could include history, autofill, and downloads.}} ++ =1 {Your organization automatically closes OpenBrowser when it isn't used for 1 minute. Browsing data is deleted. This could include history, autofill, and downloads.} ++ other {Your organization automatically closes OpenBrowser when it isn't used for # minutes. Browsing data is deleted. This could include history, autofill, and downloads.}} + + +- Continue using Chromium ++ Continue using OpenBrowser + + + + + +- Help us improve Chromium ++ Help us improve OpenBrowser + + + +@@ -2315,129 +2315,129 @@ Chromium is unable to recover your settings. + + + +- Your parent has turned off "Permissions for sites, apps and extensions" for Chromium ++ Your parent has turned off "Permissions for sites, apps and extensions" for OpenBrowser + + + +- Another program on your computer added an app that may change the way Chromium works. ++ Another program on your computer added an app that may change the way OpenBrowser works. + + $1Babylon Toolbar + + +- Another program on your computer added an extension that may change the way Chromium works. ++ Another program on your computer added an extension that may change the way OpenBrowser works. + + $1Babylon Toolbar + + +- Another program on your computer added a theme that may change the way Chromium works. ++ Another program on your computer added a theme that may change the way OpenBrowser works. + + $1Babylon Toolbar + + +- $1Google has added an extension that may change the way Chromium works. ++ $1Google has added an extension that may change the way OpenBrowser works. + + $2Babylon Toolbar + + +- Remove from Chromium ++ Remove from OpenBrowser + + + + + + +- Your organization can see and manage browsing data, such as your bookmarks, history, and passwords. It can't see browsing data in other Chromium profiles ++ Your organization can see and manage browsing data, such as your bookmarks, history, and passwords. It can't see browsing data in other OpenBrowser profiles + + + +- Welcome to Chromium profiles ++ Welcome to OpenBrowser profiles + +- +- Who's using Chromium? ++ ++ Who's using OpenBrowser? + + +- Keep everything in Chromium ++ Keep everything in OpenBrowser + + +- With Chromium profiles, you can separate all your Chromium stuff. Create profiles for friends and family, or split between work and fun. ++ With OpenBrowser profiles, you can separate all your OpenBrowser stuff. Create profiles for friends and family, or split between work and fun. + + +- Chromium profiles let you keep personal browsing and work apart. Add a new profile now. ++ OpenBrowser profiles let you keep personal browsing and work apart. Add a new profile now. + + +- Chromium profiles help you separate different parts of your life. Add a new profile now. ++ OpenBrowser profiles help you separate different parts of your life. Add a new profile now. + + +- Add a new Chromium profile to keep bookmarks, passwords, and settings apart. ++ Add a new OpenBrowser profile to keep bookmarks, passwords, and settings apart. + + +- Set up your new Chromium profile ++ Set up your new OpenBrowser profile + + +- Each profile holds its own Chromium info like bookmarks, history, passwords, and more ++ Each profile holds its own OpenBrowser info like bookmarks, history, passwords, and more + + +- If you share a device, friends and family can browse separately and set up Chromium just the way they want ++ If you share a device, friends and family can browse separately and set up OpenBrowser just the way they want + + +- Switch to existing Chromium profile? ++ Switch to existing OpenBrowser profile? + + +- A Chromium profile with this account already exists on this device ++ A OpenBrowser profile with this account already exists on this device + + +- To use this profile with Glic, open Chromium and sign in ++ To use this profile with Glic, open OpenBrowser and sign in + + + + +- Sign in to Chromium ++ desc="This string appears as a heading on a full-page screen that asks the user to sign in to OpenBrowser with their Google Account. It appears when the user launches OpenBrowser for the first time. When they sign in, they can personalize and customize OpenBrowser and remember their settings in their Google Account. The tone should be inviting and alluring."> ++ Sign in to OpenBrowser + + + +- +- Set Chromium as your default browser ++ ++ Set OpenBrowser as your default browser + +- +- Use Chromium by default and get it pinned ++ ++ Use OpenBrowser by default and get it pinned + +- +- Use Chromium anytime you click links in messages, documents, and other apps ++ ++ Use OpenBrowser anytime you click links in messages, documents, and other apps + +- +- Open links in Chromium from any app. Plus for easy access, it gets pinned to your taskbar. ++ ++ Open links in OpenBrowser from any app. Plus for easy access, it gets pinned to your taskbar. + +- +- Chromium logo inside a computer screen. ++ ++ OpenBrowser logo inside a computer screen. + + +- Customize and control Chromium. Set Chromium as your default. ++ Customize and control OpenBrowser. Set OpenBrowser as your default. + + +- Set Chromium as your default ++ Set OpenBrowser as your default + +- +- Set Chromium as your default browser ++ ++ Set OpenBrowser as your default browser + + + + +- You can switch between Chromium profiles here ++ You can switch between OpenBrowser profiles here + + +- $1CTRL+SHIFT+M can switch between Chromium profiles ++ $1CTRL+SHIFT+M can switch between OpenBrowser profiles + + +- You can switch to see passwords from another Chromium profile ++ You can switch to see passwords from another OpenBrowser profile + + + +- +- To remove your Google Account from Chromium, sign out ++ ++ To remove your Google Account from OpenBrowser, sign out + +- +- To remove your Google Account from Chromium, sign out of Chromium in the Settings page ++ ++ To remove your Google Account from OpenBrowser, sign out of OpenBrowser in the Settings page + + + +@@ -2451,20 +2451,20 @@ Chromium is unable to recover your settings. + + + +- Your changes will take effect the next time you relaunch Chromium. ++ Your changes will take effect the next time you relaunch OpenBrowser. + + + + +- Chromium needs Bluetooth access to explore Bluetooth devices. $1Open Preferences ++ OpenBrowser needs Bluetooth access to explore Bluetooth devices. $1Open Preferences + + + + +- Get Chromium's strongest security ++ Get OpenBrowser's strongest security + + +- Get Chromium's strongest security ++ Get OpenBrowser's strongest security + + + Enhanced protection does more to block phishing and malware +@@ -2478,24 +2478,24 @@ Chromium is unable to recover your settings. + + + +- Speeds up sites with Chromium's V8 engine but makes Chromium slightly less resistant to attacks. This setting is on. ++ Speeds up sites with OpenBrowser's V8 engine but makes OpenBrowser slightly less resistant to attacks. This setting is on. + + +- Speeds up sites with Chromium's V8 engine but makes Chromium slightly less resistant to attacks. This setting is off. ++ Speeds up sites with OpenBrowser's V8 engine but makes OpenBrowser slightly less resistant to attacks. This setting is off. + + +- Speeds up sites with Chromium's V8 engine but makes Chromium slightly less resistant to attacks ++ Speeds up sites with OpenBrowser's V8 engine but makes OpenBrowser slightly less resistant to attacks + + +- Chromium runs faster and features that use JavaScript should work as designed ++ OpenBrowser runs faster and features that use JavaScript should work as designed + + +- Reduces performance but makes Chromium more resistant to attacks ++ Reduces performance but makes OpenBrowser more resistant to attacks + +- ++ + + +- Chromium ++ OpenBrowser + + + No update is available. +@@ -2504,7 +2504,7 @@ Chromium is unable to recover your settings. + Installation failed. Please try again. + + +- $1Chromium Installer ++ $1OpenBrowser Installer + + + Close +@@ -2543,13 +2543,13 @@ Chromium is unable to recover your settings. + Canceling... + + +- Thanks for installing. You must restart your browser before using $1Chromium. ++ Thanks for installing. You must restart your browser before using $1OpenBrowser. + + +- Thanks for installing. You must restart all your browsers before using $1Chromium. ++ Thanks for installing. You must restart all your browsers before using $1OpenBrowser. + + +- Thanks for installing. You must restart your computer before using $1Chromium. ++ Thanks for installing. You must restart your computer before using $1OpenBrowser. + + + Close +@@ -2609,7 +2609,7 @@ Chromium is unable to recover your settings. + + +- Unable to connect to the Internet. If you use a firewall, please ensure $1ChromiumUpdater.exe is in the allowlist. ++ Unable to connect to the Internet. If you use a firewall, please ensure $1OpenBrowserUpdater.exe is in the allowlist. + + +@@ -2735,22 +2735,22 @@ Chromium is unable to recover your settings. + + +- Chromium Updater Service ++ OpenBrowser Updater Service + + +- Chromium Updater Internal Service ++ OpenBrowser Updater Internal Service + + +- Keeps your Chromium software up to date. If this service is disabled or stopped, your Chromium software will not be kept up to date, meaning security vulnerabilities that may arise cannot be fixed and features may not work. This service uninstalls itself when there is no Chromium software using it. ++ Keeps your OpenBrowser software up to date. If this service is disabled or stopped, your OpenBrowser software will not be kept up to date, meaning security vulnerabilities that may arise cannot be fixed and features may not work. This service uninstalls itself when there is no OpenBrowser software using it. + + + + + + +- While this tab was inactive, memory was freed up to keep Chromium fast. You can choose to always exclude this site from being inactive. ++ While this tab was inactive, memory was freed up to keep OpenBrowser fast. You can choose to always exclude this site from being inactive. + + + +@@ -2758,12 +2758,12 @@ Chromium is unable to recover your settings. + + + +- Make Chromium Faster ++ Make OpenBrowser Faster + + + + +- Make Chromium faster ++ Make OpenBrowser faster + + + +@@ -2771,70 +2771,70 @@ Chromium is unable to recover your settings. + + + +- These tabs are using extra resources. To improve your performance, let Chromium make them inactive. ++ These tabs are using extra resources. To improve your performance, let OpenBrowser make them inactive. + + +- This tab is using extra resources. To improve your performance, let Chromium make it inactive. ++ This tab is using extra resources. To improve your performance, let OpenBrowser make it inactive. + + + + {NUM_TABS, plural, +- =1 {Chromium Recommends Pausing the Tab Slowing Your Browser} +- other {Chromium Recommends Pausing the Tabs Slowing Your Browser}} ++ =1 {OpenBrowser Recommends Pausing the Tab Slowing Your Browser} ++ other {OpenBrowser Recommends Pausing the Tabs Slowing Your Browser}} + + + + + {NUM_TABS, plural, +- =1 {Chromium recommends pausing the tab slowing your browser} +- other {Chromium recommends pausing the tabs slowing your browser}} ++ =1 {OpenBrowser recommends pausing the tab slowing your browser} ++ other {OpenBrowser recommends pausing the tabs slowing your browser}} + + + + + + +- To delete browsing data from this device only, while keeping it in your Google Account, <a href="#" target="_blank">sign out of Chromium</a>. ++ To delete browsing data from this device only, while keeping it in your Google Account, <a href="#" target="_blank">sign out of OpenBrowser</a>. + + + + +- +- Shortcuts open in Chromium ++ ++ Shortcuts open in OpenBrowser + + + + +- Chromium Shortcut ++ OpenBrowser Shortcut + + + + + + +- Cleared Chromium data ++ Cleared OpenBrowser data + + + + + + +- Try Gemini in Chromium ++ Try Gemini in OpenBrowser + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + +- Close Gemini in Chromium ++ Close Gemini in OpenBrowser + + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + + Open Gemini (Canary) +@@ -2846,7 +2846,7 @@ Chromium is unable to recover your settings. + Open Gemini (Beta) + + +- Close Gemini in Chromium ++ Close Gemini in OpenBrowser + + + Close Gemini (Canary) +@@ -2858,7 +2858,7 @@ Chromium is unable to recover your settings. + Close Gemini (Beta) + + +- Toggle Gemini in Chromium ++ Toggle Gemini in OpenBrowser + + + Toggle Gemini (Canary) +@@ -2870,76 +2870,76 @@ Chromium is unable to recover your settings. + Toggle Gemini (Beta) + + +- Open Gemini in Chromium ++ Open Gemini in OpenBrowser + + +- Close Gemini in Chromium ++ Close Gemini in OpenBrowser + + +- Toggle Gemini in Chromium ++ Toggle Gemini in OpenBrowser + + +- To use Gemini in Chromium, sign in with a different Google Account ++ To use Gemini in OpenBrowser, sign in with a different Google Account + + + + +- Gemini in Chromium ++ Gemini in OpenBrowser + + +- Gemini in Chromium ++ Gemini in OpenBrowser + + +- Gemini in Chromium ++ Gemini in OpenBrowser + + + + +- Choose a Chromium profile to use with <span class="glic-brand-style">Glic</span> ++ Choose a OpenBrowser profile to use with <span class="glic-brand-style">Glic</span> + + +- Sign into Chromium with your Google Account to use <span class="glic-brand-style">Glic</span> ++ Sign into OpenBrowser with your Google Account to use <span class="glic-brand-style">Glic</span> + + +- Select the Chromium profile linked to your Google Account to personalize your Glic experience ++ Select the OpenBrowser profile linked to your Google Account to personalize your Glic experience + + +- To add a new profile and use it with Glic, sign in to Chromium with a Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to sign in to Chromium</a> ++ To add a new profile and use it with Glic, sign in to OpenBrowser with a Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to sign in to OpenBrowser</a> + + +- To add a new profile and use it with Glic, sign in to Chromium with a different Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to add a new Chromium profile</a> ++ To add a new profile and use it with Glic, sign in to OpenBrowser with a different Google Account. <a class="learn-more-link" href="#" target="_blank">Learn how to add a new OpenBrowser profile</a> + + + + +- To open Gemini in Chromium, press $1⌘+G ++ To open Gemini in OpenBrowser, press $1⌘+G + + + + + + +- To get this extension and more on all your computers, sign in to Chromium ++ To get this extension and more on all your computers, sign in to OpenBrowser + + + + + +- To get this bookmark and more on all your devices, sign in to Chromium ++ To get this bookmark and more on all your devices, sign in to OpenBrowser + + + + +- Get more when you’re signed in to Chromium ++ Get more when you’re signed in to OpenBrowser + + +- You’ll save and use passwords and more in your Google Account whenever you’re signed in to Chromium. $1Learn more ++ You’ll save and use passwords and more in your Google Account whenever you’re signed in to OpenBrowser. $1Learn more + + + Got it + + +- You now have more features available in Chromium ++ You now have more features available in OpenBrowser + + + Manage +@@ -2949,12 +2949,12 @@ Chromium is unable to recover your settings. + + + +- Your Account in Chromium ++ Your Account in OpenBrowser + + + + +- Your account in Chromium ++ Your account in OpenBrowser + + + +@@ -2962,30 +2962,30 @@ Chromium is unable to recover your settings. + + + +- Download Chromium on your phone to add an extra layer of protection when you're on the go ++ Download OpenBrowser on your phone to add an extra layer of protection when you're on the go + + +- Stay safer on the go with Enhanced Safe Browsing on Chromium for iOS ++ Stay safer on the go with Enhanced Safe Browsing on OpenBrowser for iOS + + +- Sign in faster to sites using saved passwords for Chromium on iOS ++ Sign in faster to sites using saved passwords for OpenBrowser on iOS + + +- You'll see a prompt to try $1Google Lens next time you open Chromium iOS. ++ You'll see a prompt to try $1Google Lens next time you open OpenBrowser iOS. + + +- Next time you open Chromium on your $1iPhone, you'll see a prompt to use Google Password Manager. ++ Next time you open OpenBrowser on your $1iPhone, you'll see a prompt to use Google Password Manager. + + + + + ++ desc="Title of the notification shown when OpenBrowser resets the default search engine (DSE) due to preference tampering."> + Your settings were changed by an unknown app + + +- Your default search engine was changed from outside of Chromium. To protect you, Chromium reset it. ++ desc="Body text of the notification shown when OpenBrowser resets the default search engine, explaining that a change from outside OpenBrowser was detected."> ++ Your default search engine was changed from outside of OpenBrowser. To protect you, OpenBrowser reset it. + + +diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd +index 87032bcf74573..46e0a70ccd789 100644 +--- a/chrome/app/generated_resources.grd ++++ b/chrome/app/generated_resources.grd +@@ -1644,7 +1644,7 @@ are declared in tools/grit/grit_args.gni. + Name &window... + + +- Chrome &Labs... ++ OpenBrowser &Labs... + + + +@@ -1694,7 +1694,7 @@ are declared in tools/grit/grit_args.gni. + Name &Window... + + +- Chrome &Labs... ++ OpenBrowser &Labs... + + + +@@ -1782,7 +1782,7 @@ are declared in tools/grit/grit_args.gni. + Manage Extensions + + +- Visit Chrome Web Store ++ Visit OpenBrowser Web Store + + + Performance +@@ -1841,7 +1841,7 @@ are declared in tools/grit/grit_args.gni. + Manage Extensions + + +- Visit Chrome Web Store ++ Visit OpenBrowser Web Store + + + Performance +@@ -7852,7 +7852,7 @@ Keep your key file in a safe place. You will need it to create new versions of y + Cards + + +- Default Chrome ++ Default OpenBrowser + + + Change theme +@@ -7860,7 +7860,7 @@ Keep your key file in a safe place. You will need it to create new versions of y + + Footer + +- ++ + Search tools + + +@@ -7873,10 +7873,10 @@ Keep your key file in a safe place. You will need it to create new versions of y + $1ZomboCom is managing your new tab page, opens in a new tab + + +- Reset to Default Chrome ++ Reset to Default OpenBrowser + + +- Theme updated to Default Chrome ++ Theme updated to Default OpenBrowser + + + Theme updated to uploaded image +diff --git a/chrome/app/theme/chromium/mac/app.icns b/chrome/app/theme/chromium/mac/app.icns +index 97072c8c1157d..2ec93f208bae4 100644 +Binary files a/chrome/app/theme/chromium/mac/app.icns and b/chrome/app/theme/chromium/mac/app.icns differ +diff --git a/chrome/app/theme/chromium/product_logo.svg b/chrome/app/theme/chromium/product_logo.svg +index 5e0b254b8dbaf..e10b921abd6b1 100644 +--- a/chrome/app/theme/chromium/product_logo.svg ++++ b/chrome/app/theme/chromium/product_logo.svg +@@ -1 +1,4 @@ +- +\ No newline at end of file ++ ++ ++ ++ +diff --git a/chrome/app/theme/chromium/product_logo_128.png b/chrome/app/theme/chromium/product_logo_128.png +index 9ce48f920e87c..c901d2e6081a6 100644 +Binary files a/chrome/app/theme/chromium/product_logo_128.png and b/chrome/app/theme/chromium/product_logo_128.png differ +diff --git a/chrome/app/theme/chromium/product_logo_16.png b/chrome/app/theme/chromium/product_logo_16.png +index ce9084c733b2c..c6a9634b7a797 100644 +Binary files a/chrome/app/theme/chromium/product_logo_16.png and b/chrome/app/theme/chromium/product_logo_16.png differ +diff --git a/chrome/app/theme/chromium/product_logo_22_mono.png b/chrome/app/theme/chromium/product_logo_22_mono.png +index b8874d44bcde3..d7259c33706a9 100644 +Binary files a/chrome/app/theme/chromium/product_logo_22_mono.png and b/chrome/app/theme/chromium/product_logo_22_mono.png differ +diff --git a/chrome/app/theme/chromium/product_logo_24.png b/chrome/app/theme/chromium/product_logo_24.png +index d883fde3daa7e..d0d6d6cbbecb4 100644 +Binary files a/chrome/app/theme/chromium/product_logo_24.png and b/chrome/app/theme/chromium/product_logo_24.png differ +diff --git a/chrome/app/theme/chromium/product_logo_256.png b/chrome/app/theme/chromium/product_logo_256.png +index 4899f69aaba5c..16a8fe006b718 100644 +Binary files a/chrome/app/theme/chromium/product_logo_256.png and b/chrome/app/theme/chromium/product_logo_256.png differ +diff --git a/chrome/app/theme/chromium/product_logo_48.png b/chrome/app/theme/chromium/product_logo_48.png +index 9ec8436cbf853..b9c78d0e08a37 100644 +Binary files a/chrome/app/theme/chromium/product_logo_48.png and b/chrome/app/theme/chromium/product_logo_48.png differ +diff --git a/chrome/app/theme/chromium/product_logo_64.png b/chrome/app/theme/chromium/product_logo_64.png +index 8bd239e39c653..d47e06130b0d7 100644 +Binary files a/chrome/app/theme/chromium/product_logo_64.png and b/chrome/app/theme/chromium/product_logo_64.png differ +diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_16.png b/chrome/app/theme/default_100_percent/chromium/product_logo_16.png +index 77ac0f31cb21d..c6a9634b7a797 100644 +Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_16.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_16.png differ +diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_32.png b/chrome/app/theme/default_100_percent/chromium/product_logo_32.png +index 175b2917c9ee5..bf888d0de92fe 100644 +Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_32.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_32.png differ +diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png +index addde0e37401b..b7fe29c00d79d 100644 +Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png differ +diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png +index 0cf6cfc1d5a1b..ae6a1238beb5d 100644 +Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png differ +diff --git a/chrome/app/theme/default_100_percent/common/favicon_ntp.png b/chrome/app/theme/default_100_percent/common/favicon_ntp.png +index 79291d8c90432..2ce13a8cadaf3 100644 +Binary files a/chrome/app/theme/default_100_percent/common/favicon_ntp.png and b/chrome/app/theme/default_100_percent/common/favicon_ntp.png differ +diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_16.png b/chrome/app/theme/default_200_percent/chromium/product_logo_16.png +index 2b5899e392fb8..c6a9634b7a797 100644 +Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_16.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_16.png differ +diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_32.png b/chrome/app/theme/default_200_percent/chromium/product_logo_32.png +index 886113df438c5..bf888d0de92fe 100644 +Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_32.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_32.png differ +diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png +index a611e83849a50..8e4c9f9ee9560 100644 +Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png differ +diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png +index 926247cb9f8af..87cd9fee473bd 100644 +Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png differ +diff --git a/chrome/app/theme/default_200_percent/common/favicon_ntp.png b/chrome/app/theme/default_200_percent/common/favicon_ntp.png +index 841d0a4d3eaaa..6286728c00000 100644 +Binary files a/chrome/app/theme/default_200_percent/common/favicon_ntp.png and b/chrome/app/theme/default_200_percent/common/favicon_ntp.png differ +diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd +index 87c3c8382e602..d38aa879d082b 100644 +--- a/chrome/app/theme/theme_resources.grd ++++ b/chrome/app/theme/theme_resources.grd +@@ -160,6 +160,7 @@ + + + ++ + + + +diff --git a/chrome/browser/favicon/favicon_utils.cc b/chrome/browser/favicon/favicon_utils.cc +index eff6b7ccc596b..774d653bdcc98 100644 +--- a/chrome/browser/favicon/favicon_utils.cc ++++ b/chrome/browser/favicon/favicon_utils.cc +@@ -213,34 +213,16 @@ gfx::ImageSkia ThemeFavicon(const gfx::ImageSkia& source, + SkColor alternate_color, + SkColor active_background, + SkColor inactive_background) { +- // Choose between leaving the image as-is or masking with |alternate_color|. +- const SkColor original_color = +- color_utils::CalculateKMeanColorOfBitmap(*source.bitmap()); +- +- // Compute the minimum contrast of each color against active and inactive +- // backgrounds. +- const float original_contrast = std::min( +- color_utils::GetContrastRatio(original_color, active_background), +- color_utils::GetContrastRatio(original_color, inactive_background)); +- const float alternate_contrast = std::min( +- color_utils::GetContrastRatio(alternate_color, active_background), +- color_utils::GetContrastRatio(alternate_color, inactive_background)); +- +- // Recolor the image if the original has low minimum contrast and recoloring +- // will improve it. +- return ((original_contrast < color_utils::kMinimumVisibleContrastRatio) && +- (alternate_contrast > original_contrast)) +- ? gfx::ImageSkiaOperations::CreateColorMask(source, +- alternate_color) +- : source; ++ // Always apply the alternate color (black/white theme) ++ return gfx::ImageSkiaOperations::CreateColorMask(source, alternate_color); + } + + gfx::ImageSkia ThemeMonochromeFavicon(const gfx::ImageSkia& source, + SkColor background) { +- return (color_utils::GetContrastRatio(gfx::kGoogleGrey900, background) > ++ return (color_utils::GetContrastRatio(SK_ColorBLACK, background) > + color_utils::GetContrastRatio(SK_ColorWHITE, background)) + ? gfx::ImageSkiaOperations::CreateColorMask(source, +- gfx::kGoogleGrey900) ++ SK_ColorBLACK) + : gfx::ImageSkiaOperations::CreateColorMask(source, SK_ColorWHITE); + } + +diff --git a/chrome/browser/resources/new_tab_page/app.css b/chrome/browser/resources/new_tab_page/app.css +index e478fea59f056..7f971831f25b6 100644 +--- a/chrome/browser/resources/new_tab_page/app.css ++++ b/chrome/browser/resources/new_tab_page/app.css +@@ -57,18 +57,18 @@ + */ + :host([realbox-can-show-secondary-side][realbox-had-secondary-side]), + :host([realbox-can-show-secondary-side]) { +- --ntp-search-box-width: 746px; ++ --ntp-search-box-width: 900px; + } + + @media (min-width: 560px) { + :host { +- --ntp-search-box-width: 449px; ++ --ntp-search-box-width: 600px; + } + } + + @media (min-width: 672px) { + :host { +- --ntp-search-box-width: 561px; ++ --ntp-search-box-width: 750px; + } + } + +diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts +index 167ae9b24c89f..b3e65a5d99076 100644 +--- a/chrome/browser/resources/new_tab_page/app.ts ++++ b/chrome/browser/resources/new_tab_page/app.ts +@@ -1160,10 +1160,8 @@ export class AppElement extends AppElementBase { + } + + protected computeShowBrowserPromo_(): boolean { +- return !this.modulesEnabled_ || +- (this.modulesLoadedStatus_ !== +- ModuleLoadStatus.MODULE_LOAD_IN_PROGRESS && +- !this.modulesShownToUser); ++ // Disabled: Don't show "Make OpenBrowser Yours" setup list ++ return false; + } + + protected recordBrowserPromoMetrics_() { +diff --git a/chrome/browser/resources/new_tab_page/icons/BUILD.gn b/chrome/browser/resources/new_tab_page/icons/BUILD.gn +index 3ebefc4d55512..a21d09c60109d 100644 +--- a/chrome/browser/resources/new_tab_page/icons/BUILD.gn ++++ b/chrome/browser/resources/new_tab_page/icons/BUILD.gn +@@ -16,7 +16,8 @@ generate_grd("build_grdp") { + "drive_logo.svg", + "facebook.svg", + "generic_globe.svg", +- "google_logo.svg", ++ "openbrowser_logo_white.png", ++ "openbrowser_logo_black.png", + "info.svg", + "link.svg", + "mail.svg", +diff --git a/chrome/browser/resources/new_tab_page/logo.css b/chrome/browser/resources/new_tab_page/logo.css +index e744ffca3bf37..53c71d3ece9b0 100644 +--- a/chrome/browser/resources/new_tab_page/logo.css ++++ b/chrome/browser/resources/new_tab_page/logo.css +@@ -25,18 +25,18 @@ + #logo { + forced-color-adjust: none; + height: 92px; +- width: 272px; ++ width: 830px; ++ background-repeat: no-repeat; ++ background-size: contain; ++ background-position: center; + } + +-:host([single-colored]) #logo { +- -webkit-mask-image: url(./icons/google_logo.svg); +- -webkit-mask-repeat: no-repeat; +- -webkit-mask-size: 100%; +- background-color: var(--ntp-logo-color); ++:host([is-dark]) #logo { ++ background-image: url(./icons/openbrowser_logo_white.png); + } + +-:host(:not([single-colored])) #logo { +- background-image: url(./icons/google_logo.svg); ++:host(:not([is-dark])) #logo { ++ background-image: url(./icons/openbrowser_logo_black.png); + } + + #imageDoodle { +diff --git a/chrome/browser/resources/new_tab_page/logo.ts b/chrome/browser/resources/new_tab_page/logo.ts +index ac93b867d21c4..fea17c4478205 100644 +--- a/chrome/browser/resources/new_tab_page/logo.ts ++++ b/chrome/browser/resources/new_tab_page/logo.ts +@@ -52,6 +52,11 @@ export class LogoElement extends CrLitElement { + */ + theme: {type: Object}, + ++ isDark: { ++ reflect: true, ++ type: Boolean, ++ }, ++ + loaded_: {type: Boolean}, + doodle_: {type: Object}, + imageDoodle_: {type: Object}, +@@ -78,6 +83,7 @@ export class LogoElement extends CrLitElement { + + accessor singleColored: boolean = false; + accessor theme: Theme|null = null; ++ accessor isDark: boolean = false; + private accessor loaded_: boolean = false; + protected accessor doodle_: Doodle|null = null; + protected accessor imageDoodle_: ImageDoodle|null = null; +@@ -143,6 +149,7 @@ export class LogoElement extends CrLitElement { + override willUpdate(changedProperties: PropertyValues) { + super.willUpdate(changedProperties); + ++ this.isDark = !!(this.theme && this.theme.isDark); + this.imageDoodle_ = this.computeImageDoodle_(); + this.imageUrl_ = this.computeImageUrl_(); + this.animationUrl_ = this.computeAnimationUrl_(); +diff --git a/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg b/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg +index 83221a8e6f90f..ea3bc8cf4b002 100644 +--- a/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg ++++ b/chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg +@@ -1 +1,77 @@ +- +\ No newline at end of file ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc +index 8634cbb4dc17a..ef53ad2540d79 100644 +--- a/chrome/browser/themes/theme_service_factory.cc ++++ b/chrome/browser/themes/theme_service_factory.cc +@@ -139,6 +139,7 @@ void ThemeServiceFactory::RegisterProfilePrefs( + registry->RegisterIntegerPref( + prefs::kDeprecatedUserColorDoNotUse, SK_ColorTRANSPARENT, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); ++ // Use transparent to indicate no custom color (will use baseline grayscale) + registry->RegisterIntegerPref(prefs::kUserColor, SK_ColorTRANSPARENT); + registry->RegisterIntegerPref( + prefs::kDeprecatedBrowserColorVariantDoNotUse, +diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +index 350f052b92aef..36dec424c89f2 100644 +--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +@@ -407,7 +407,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) + : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorSearchboxForeground] = +- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) + : ui::ColorTransform(SK_ColorBLACK)}; + mixer[kColorSearchboxPlaceholder] = + {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) +@@ -440,7 +440,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) + : gfx::kGoogleBlue600}; + mixer[kColorSearchboxResultsForeground] = +- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) + : ui::ColorTransform(SK_ColorBLACK)}; + mixer[kColorSearchboxResultsForegroundDimmed] = + {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) +diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +index 3544f1b569ee1..760b5a59e82df 100644 +--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc ++++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +@@ -626,7 +626,7 @@ gfx::RoundedCornersF IconLabelBubbleView::GetCornerRadii() const { + if (radii_.has_value()) { + return radii_.value(); + } +- return gfx::RoundedCornersF(GetPreferredSize().height() / 2); ++ return gfx::RoundedCornersF(4); + } + + void IconLabelBubbleView::SetCornerRadii(const gfx::RoundedCornersF& radii) { +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc +index 2dbe7d318cd7b..989abffe08143 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc +@@ -245,7 +245,7 @@ LocationBarView::LocationBarView(Browser* browser, + !v->GetOmniboxController()->IsPopupOpen(); + })); + views::FocusRing::Get(this)->SetOutsetFocusRingDisabled(true); +- views::InstallPillHighlightPathGenerator(this); ++ views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), 8); + + #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) + if (features::IsOsLevelGeolocationPermissionSupportEnabled()) { +diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc +index d5306a85b1e0c..40c9d0ffd3971 100644 +--- a/chrome/browser/ui/views/tabs/tab.cc ++++ b/chrome/browser/ui/views/tabs/tab.cc +@@ -372,8 +372,20 @@ void Tab::Layout(PassKey) { + + // The bounds for the favicon will include extra width for the attention + // indicator, but visually it will be smaller at kFaviconSize wide. +- gfx::Rect favicon_bounds(start, contents_rect.y(), 0, 0); ++ ++ gfx::Rect favicon_bounds; + if (showing_icon_) { ++ const gfx::Size icon_size = icon_->GetPreferredSize(); ++ const gfx::Insets icon_insets = icon_->GetInsets(); ++ ++ // Center the favicon vertically so its middle aligns with the content area ++ // middle. We need to add the inset back because Inset(-insets) will ++ // subtract it later. ++ const int content_middle_y = contents_rect.y() + contents_rect.height() / 2; ++ const int favicon_y = content_middle_y - icon_size.height() / 2 + icon_insets.top(); ++ ++ favicon_bounds = gfx::Rect(start, favicon_y, 0, 0); ++ + if (center_icon_) { + // When centering the favicon, the favicon is allowed to escape the normal + // contents rect. +@@ -389,7 +401,9 @@ void Tab::Layout(PassKey) { + + // Add space for insets outside the favicon bounds. + favicon_bounds.Inset(-icon_->GetInsets()); +- favicon_bounds.set_size(icon_->GetPreferredSize()); ++ favicon_bounds.set_size(icon_size); ++ } else { ++ favicon_bounds = gfx::Rect(start, contents_rect.y(), 0, 0); + } + icon_->SetBoundsRect(favicon_bounds); + icon_->SetVisible(showing_icon_); +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +index 832ca90c1538c..ce053294b3ad0 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +@@ -616,13 +616,8 @@ void NewTabPageHandler::GetMostVisitedSettings( + } + + void NewTabPageHandler::GetDoodle(GetDoodleCallback callback) { +- search_provider_logos::LogoCallbacks callbacks; +- callbacks.on_cached_encoded_logo_available = +- base::BindOnce(&NewTabPageHandler::OnLogoAvailable, +- weak_ptr_factory_.GetWeakPtr(), std::move(callback)); +- // This will trigger re-downloading the doodle and caching it. This means a +- // new doodle will be returned on subsequent NTP loads. +- logo_service_->GetLogo(std::move(callbacks), /*for_webui_ntp=*/true); ++ // Disable Google doodle downloading - always return null to use local logo ++ std::move(callback).Run(nullptr); + } + + void NewTabPageHandler::UpdatePromoData() { +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +index 12651b3c1e9b0..ff46a3238a763 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +@@ -211,9 +211,8 @@ content::WebUIDataSource* CreateAndAddNewTabPageUiHtmlSource(Profile* profile) { + source->AddBoolean( + "ntpNextFeaturesEnabled", + base::FeatureList::IsEnabled(ntp_features::kNtpNextFeatures)); +- source->AddBoolean( +- "oneGoogleBarEnabled", +- base::FeatureList::IsEnabled(ntp_features::kNtpOneGoogleBar)); ++ // Disable One Google Bar (contains Gmail and Images links) ++ source->AddBoolean("oneGoogleBarEnabled", false); + source->AddBoolean("shortcutsEnabled", + base::FeatureList::IsEnabled(ntp_features::kNtpShortcuts)); + source->AddBoolean("logoEnabled", +@@ -577,10 +576,8 @@ content::WebUIDataSource* CreateAndAddNewTabPageUiHtmlSource(Profile* profile) { + ContextualSearchSourceToString( + contextual_search::ContextualSearchSource::kNewTabPage)); + +- source->AddBoolean( +- "searchboxShowComposeEntrypoint", +- (ntp_composebox::IsNtpSearchboxComposeEntrypointEnabled(profile) || +- ntp_composebox::IsNtpComposeboxEnabled(profile))); ++ // Disable AI Mode button ++ source->AddBoolean("searchboxShowComposeEntrypoint", false); + + if (ntp_realbox::IsNtpRealboxNextEnabled(profile)) { + switch (ntp_realbox::kSteadyPlaceholder.Get()) { +diff --git a/components/omnibox/browser/vector_icons/product_chrome_refresh.icon b/components/omnibox/browser/vector_icons/product_chrome_refresh.icon +index 5c35bda0d736b..2f3d804fbb80e 100644 +--- a/components/omnibox/browser/vector_icons/product_chrome_refresh.icon ++++ b/components/omnibox/browser/vector_icons/product_chrome_refresh.icon +@@ -1,51 +1,25 @@ +-// Copyright 2023 The Chromium Authors +-// Use of this source code is governed by a BSD-style license that can be +-// found in the LICENSE file. ++CANVAS_DIMENSIONS, 40, + +-CANVAS_DIMENSIONS, 15, +-MOVE_TO, 4.92, 7.5, +-R_CUBIC_TO, 0, 0.71, 0.25, 1.31, 0.76, 1.82, +-R_CUBIC_TO, 0.51, 0.51, 1.12, 0.76, 1.82, 0.76, +-R_CUBIC_TO, 0.7, 0, 1.31, -0.25, 1.82, -0.76, +-R_CUBIC_TO, 0.51, -0.51, 0.76, -1.12, 0.76, -1.82, +-R_CUBIC_TO, 0, -0.7, -0.25, -1.31, -0.76, -1.82, +-R_ARC_TO, 2.49, 2.49, 0, 0, 0, -1.82, -0.76, +-R_CUBIC_TO, -0.7, 0, -1.31, 0.25, -1.82, 0.76, +-R_ARC_TO, 2.49, 2.49, 0, 0, 0, -0.76, 1.82, ++MOVE_TO, 0, 0, ++H_LINE_TO, 30, ++V_LINE_TO, 40, ++H_LINE_TO, 0, + CLOSE, +-MOVE_TO, 7.5, 11.48, +-R_CUBIC_TO, 0.14, 0, 0.28, 0, 0.41, -0.02, +-R_CUBIC_TO, 0.13, -0.01, 0.26, -0.04, 0.39, -0.07, +-LINE_TO, 6.77, 14.06, +-R_CUBIC_TO, -1.65, -0.19, -3.04, -0.89, -4.15, -2.12, +-CUBIC_TO, 1.5, 10.71, 0.94, 9.24, 0.94, 7.55, +-R_CUBIC_TO, 0, -0.46, 0.05, -0.9, 0.13, -1.33, +-R_CUBIC_TO, 0.08, -0.44, 0.22, -0.85, 0.39, -1.25, +-R_LINE_TO, 2.63, 4.55, +-R_CUBIC_TO, 0.34, 0.59, 0.81, 1.07, 1.41, 1.43, +-R_CUBIC_TO, 0.6, 0.36, 1.26, 0.54, 2.01, 0.54, ++ ++MOVE_TO, 8, 7.5, ++H_LINE_TO, 23, ++V_LINE_TO, 15.5, ++H_LINE_TO, 8, + CLOSE, +-R_MOVE_TO, 0, -7.87, +-R_CUBIC_TO, -0.87, 0, -1.65, 0.25, -2.33, 0.77, +-R_ARC_TO, 3.95, 3.95, 0, 0, 0, -1.42, 1.94, +-LINE_TO, 2.21, 3.66, +-R_ARC_TO, 6.79, 6.79, 0, 0, 1, 2.27, -1.94, +-CUBIC_TO, 5.4, 1.22, 6.4, 0.98, 7.5, 0.98, +-R_CUBIC_TO, 1.1, 0, 2.08, 0.24, 2.99, 0.72, +-ARC_TO, 6.66, 6.66, 0, 0, 1, 12.76, 3.6, +-H_LINE_TO, 7.51, +-R_LINE_TO, -0.01, 0.01, ++ ++MOVE_TO, 8, 15.5, ++H_LINE_TO, 14, ++V_LINE_TO, 23.5, ++H_LINE_TO, 8, + CLOSE, +-R_MOVE_TO, 6.01, 1.31, +-R_CUBIC_TO, 0.19, 0.4, 0.32, 0.83, 0.41, 1.27, +-R_CUBIC_TO, 0.09, 0.44, 0.15, 0.89, 0.15, 1.36, +-R_CUBIC_TO, 0, 1.7, -0.55, 3.16, -1.68, 4.38, +-R_CUBIC_TO, -1.11, 1.23, -2.47, 1.93, -4.1, 2.13, +-R_LINE_TO, 2.63, -4.55, +-R_CUBIC_TO, 0.17, -0.28, 0.29, -0.59, 0.38, -0.92, +-R_CUBIC_TO, 0.09, -0.34, 0.15, -0.69, 0.15, -1.05, +-R_CUBIC_TO, 0, -0.52, -0.09, -0.99, -0.28, -1.42, +-R_ARC_TO, 3.96, 3.96, 0, 0, 0, -0.74, -1.2, +-R_H_LINE_TO, 3.08, +-R_V_LINE_TO, 0.01, +-CLOSE ++ ++MOVE_TO, 8, 23.5, ++H_LINE_TO, 23, ++V_LINE_TO, 31.5, ++H_LINE_TO, 8, ++CLOSE +\ No newline at end of file +diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc +index 6d2ea1d68430b..406d9402d41e1 100644 +--- a/components/search/ntp_features.cc ++++ b/components/search/ntp_features.cc +@@ -98,7 +98,7 @@ BASE_FEATURE(kNtpDummyModules, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, Google Drive module will be shown. + // This is a kill switch. Keep indefinitely. +-BASE_FEATURE(kNtpDriveModule, base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpDriveModule, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, the NTP Drive module does not require sync. + BASE_FEATURE(kNtpDriveModuleHistorySyncRequirement, +@@ -121,7 +121,7 @@ BASE_FEATURE(kNtpMiddleSlotPromo, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, middle slot promo will be dismissed from New Tab Page until new + // promo message is populated +-BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_ENABLED_BY_DEFAULT); + + // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". + // This is used for an emergency Finch param. Keep indefinitely. +diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h +index d8c168edc6c92..2d8243d947b94 100644 +--- a/ui/native_theme/native_theme.h ++++ b/ui/native_theme/native_theme.h +@@ -602,7 +602,7 @@ class COMPONENT_EXPORT(NATIVE_THEME) NativeTheme { + std::optional user_color_; + std::optional scheme_variant_; + ColorProviderKey::UserColorSource preferred_color_source_ = +- ColorProviderKey::UserColorSource::kAccent; ++ ColorProviderKey::UserColorSource::kBaseline; + base::TimeDelta caret_blink_interval_; + + raw_ptr associated_web_instance_ = nullptr; +diff --git a/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn b/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn +index 8ad6296ea91dc..717abf4b71523 100644 +--- a/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn ++++ b/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn +@@ -91,7 +91,7 @@ if (is_chrome_branded) { + "google_g.svg", + "google_g_gradient.svg", + "google_g_cr23.svg", +- "google_logo.svg", ++ "openbrowser_logo_white.png", + "mic.svg", + ] + input_files_base_dir = +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.css b/ui/webui/resources/cr_components/searchbox/searchbox.css +index dc4fdb93e0fa3..5ca09ff564360 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox.css +@@ -12,7 +12,7 @@ + :host { + /* Embedders should define --cr-searchbox-min-width. */ + --cr-searchbox-width: var(--cr-searchbox-min-width); +- --cr-searchbox-border-radius: calc(0.5 * var(--cr-searchbox-height)); ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-icon-width: 26px; + --cr-searchbox-inner-icon-margin: 8px; + --cr-searchbox-voice-icon-offset: 16px; +@@ -274,11 +274,29 @@ cr-searchbox-icon { + } + + :host(:not([use-webkit-search-icons_])) #voiceSearchButton { +- background-image: url(//resources/cr_components/searchbox/icons/mic.svg); ++ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/mic.svg); ++ -webkit-mask-position: center; ++ -webkit-mask-repeat: no-repeat; ++ -webkit-mask-size: 21px 21px; + } + + :host(:not([use-webkit-search-icons_])) #lensSearchButton { +- background-image: url(//resources/cr_components/searchbox/icons/camera.svg); ++ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/camera.svg); ++ -webkit-mask-position: center; ++ -webkit-mask-repeat: no-repeat; ++ -webkit-mask-size: 21px 21px; ++} ++ ++/* White icons in dark mode */ ++:host(:not([use-webkit-search-icons_])[is-dark]) #voiceSearchButton, ++:host(:not([use-webkit-search-icons_])[is-dark]) #lensSearchButton { ++ background-color: white; ++} ++ ++/* Black icons in light mode */ ++:host(:not([use-webkit-search-icons_]):not([is-dark])) #voiceSearchButton, ++:host(:not([use-webkit-search-icons_]):not([is-dark])) #lensSearchButton { ++ background-color: black; + } + + :host([use-webkit-search-icons_]) #voiceSearchButton { +@@ -373,7 +391,7 @@ search-animated-glow { + } + + :host([ntp-realbox-next-enabled]) { +- --cr-searchbox-border-radius: 26px; ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-dropdown-padding-bottom: 12px; + /* Cannot touch this searchbox icon size var; + it's used by the rainbow outline AI button class in +@@ -540,7 +558,7 @@ search-animated-glow { + } + + :host([searchbox-layout-mode='Compact']) { +- --cr-searchbox-border-radius: 30px; ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-dropdown-padding-bottom: 10px; + --cr-searchbox-dropdown-padding-top: 10px; + --cr-searchbox-height: 56px; +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_match.css b/ui/webui/resources/cr_components/searchbox/searchbox_match.css +index 514d780649bba..48fe44b9e8788 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox_match.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox_match.css +@@ -221,13 +221,14 @@ + + .match { + font-weight: var(--cr-searchbox-match-font-weight, 600); ++ color: var(--color-searchbox-results-foreground); + } + + /* In the lens side panel searchbox, the typed prefix of the match should + * have a different color than the rest of the autocomplete suggestion. */ + :host(:not([is-top-chrome-searchbox_])) #contents span:not(.match), + #ellipsis { +- color: var(--color-searchbox-results-typed-prefix, --color-searchbox-results-foreground); ++ color: var(--color-searchbox-results-foreground); + } + + /* Used to override contents color in zero prefix matches */ +diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +index 735615a4ba785..d95689b8b1196 100644 +--- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts ++++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +@@ -15,7 +15,8 @@ export function getHtml(this: CrDrawerElement) { + + + ++ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, ++ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> + + + ++ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, ++ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> + ChromeBrowserMainParts::Create( + + main_parts->AddParts(std::make_unique()); + ++ // Add OpenBrowser extra parts for openbrowser:// scheme support (Brave-style) ++ main_parts->AddParts(std::make_unique()); ++ + chrome::AddMetricsExtraParts(main_parts.get()); + + main_parts->AddParts( +diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc +index 8da969bd542eb..aec983c3b66af 100644 +--- a/chrome/browser/chrome_content_browser_client.cc ++++ b/chrome/browser/chrome_content_browser_client.cc +@@ -2080,6 +2080,8 @@ void ChromeContentBrowserClient::GetAdditionalWebUISchemes( + additional_schemes->emplace_back(chrome::kChromeSearchScheme); + additional_schemes->emplace_back(dom_distiller::kDomDistillerScheme); + additional_schemes->emplace_back(content::kChromeDevToolsScheme); ++ // Add openbrowser:// as a WebUI scheme (like Brave adds brave://) ++ additional_schemes->emplace_back("openbrowser"); + } + + bool ChromeContentBrowserClient::IsInternalScheme(const GURL& url) { +diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn +index 28f9bc3e7ece5..e452fefebffec 100644 +--- a/chrome/browser/ui/BUILD.gn ++++ b/chrome/browser/ui/BUILD.gn +@@ -508,6 +508,7 @@ static_library("ui") { + "//components/offline_pages/buildflags", + "//components/omnibox/browser", + "//components/omnibox/browser:vector_icons", ++ "//openbrowser/common", + "//components/onc", + "//components/optimization_guide/content/browser", + "//components/optimization_guide/core", +diff --git a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc +index 9a0934f9a65c0..944118bb630d0 100644 +--- a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc ++++ b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc +@@ -28,6 +28,11 @@ + #include "components/page_info/core/pref_names.h" + #include "components/permissions/permission_decision_auto_blocker.h" + #include "components/permissions/permission_manager.h" ++#include "openbrowser/common/buildflags.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + #include "components/permissions/permissions_client.h" + #include "components/prefs/pref_service.h" + #include "components/privacy_sandbox/tracking_protection_settings.h" +@@ -63,7 +68,14 @@ + ChromePageInfoUiDelegate::ChromePageInfoUiDelegate( + content::WebContents* web_contents, + const GURL& site_url) +- : web_contents_(web_contents), site_url_(site_url) {} ++ : web_contents_(web_contents), ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ site_url_(openbrowser::GetDisplayURLForInternal(site_url)) ++#else ++ site_url_(site_url) ++#endif ++{} + + bool ChromePageInfoUiDelegate::ShouldShowAllow(ContentSettingsType type) { + switch (type) { +diff --git a/chrome/browser/ui/tabs/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/tabs/recent_tabs_sub_menu_model.cc +index 0099aba7e3000..5cbd9422238b1 100644 +--- a/chrome/browser/ui/tabs/recent_tabs_sub_menu_model.cc ++++ b/chrome/browser/ui/tabs/recent_tabs_sub_menu_model.cc +@@ -48,6 +48,11 @@ + #include "chrome/grit/generated_resources.h" + #include "components/favicon/core/history_ui_favicon_request_handler.h" + #include "components/favicon_base/favicon_types.h" ++#include "openbrowser/common/buildflags.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + #include "components/prefs/scoped_user_pref_update.h" + #include "components/sessions/core/tab_restore_service.h" + #include "components/signin/public/identity_manager/identity_manager.h" +@@ -541,11 +546,19 @@ void RecentTabsSubMenuModel::BuildLocalTabItem( + tab.navigations.at(tab.normalized_navigation_index()); + TabItem item(std::string(), tab.id, current_navigation.title(), + current_navigation.virtual_url()); ++ ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(item.url); ++#else ++ const GURL& display_url = item.url; ++#endif ++ + // See comments in BuildLocalEntries() about usage of InsertItem*At(). + // There may be no tab title, in which case, use the url as tab title. + InsertItemAt( + curr_model_index, command_id, +- item.title.empty() ? base::UTF8ToUTF16(item.url.spec()) : item.title); ++ item.title.empty() ? base::UTF8ToUTF16(display_url.spec()) : item.title); + local_tab_items_.emplace(command_id, item); + AddTabFavicon(command_id, this, item.url); + // We shouldn't get here if there is no recently closed title. +@@ -617,10 +630,18 @@ void RecentTabsSubMenuModel::BuildOtherDevicesTabItem( + tab.navigations.at(tab.normalized_navigation_index()); + TabItem item(session_tag, tab.tab_id, current_navigation.title(), + current_navigation.virtual_url()); ++ ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(item.url); ++#else ++ const GURL& display_url = item.url; ++#endif ++ + // See comments in BuildTabsFromOtherDevices() about usage of AddItem*(). + // There may be no tab title, in which case, use the url as tab title. + containing_model->AddItem(command_id, current_navigation.title().empty() +- ? base::UTF8ToUTF16(item.url.spec()) ++ ? base::UTF8ToUTF16(display_url.spec()) + : current_navigation.title()); + remote_tab_items_.emplace(command_id, item); + AddTabFavicon(command_id, containing_model, item.url); +diff --git a/chrome/browser/ui/views/bookmarks/bookmark_button.cc b/chrome/browser/ui/views/bookmarks/bookmark_button.cc +index 5078ba0b4493b..2db9baa20cead 100644 +--- a/chrome/browser/ui/views/bookmarks/bookmark_button.cc ++++ b/chrome/browser/ui/views/bookmarks/bookmark_button.cc +@@ -30,6 +30,11 @@ + #include "ui/base/ui_base_features.h" + #include "ui/views/accessibility/view_accessibility.h" + #include "ui/views/widget/tooltip_manager.h" ++#include "openbrowser/common/buildflags.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. +@@ -138,21 +143,33 @@ void BookmarkButton::UpdateTooltipText() { + return; + } + ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ // OpenBrowser: Disable URL tooltips for bookmarks (privacy/cleaner UI) ++ SetTooltipText(std::u16string()); ++#else + const views::TooltipManager* tooltip_manager = + GetWidget()->GetTooltipManager(); + if (tooltip_manager) { + SetTooltipText(BookmarkBarView::CreateToolTipForURLAndTitle( + max_tooltip_width_, tooltip_manager->GetFontList(), *url_, GetText())); + } ++#endif + } + + void BookmarkButton::AdjustAccessibleName(std::u16string& new_name, + ax::mojom::NameFrom& name_from) { + if (new_name.empty()) { ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(*url_); ++#else ++ const GURL& display_url = *url_; ++#endif ++ + new_name = l10n_util::GetStringFUTF16( + IDS_UNNAMED_BOOKMARK_BUTTON_ACCESSIBLE_NAME, + url_formatter::FormatUrl( +- url_.get(), url_formatter::kFormatUrlOmitDefaults, ++ display_url, url_formatter::kFormatUrlOmitDefaults, + base::UnescapeRule::NORMAL, nullptr, nullptr, nullptr)); + name_from = ax::mojom::NameFrom::kContents; + } +diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_button_base.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_button_base.cc +index 6c1ba4355c030..addd2c63e0ba9 100644 +--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_button_base.cc ++++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_button_base.cc +@@ -20,7 +20,8 @@ BookmarkMenuButtonBase::BookmarkMenuButtonBase(PressedCallback callback, + ConfigureInkDropForToolbar(this); + SetImageLabelSpacing(ChromeLayoutProvider::Get()->GetDistanceMetric( + DISTANCE_RELATED_LABEL_HORIZONTAL_LIST)); +- views::InstallPillHighlightPathGenerator(this); ++ // OpenBrowser: Use fixed 8px corner radius instead of pill shape ++ views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), 8); + } + + // MenuButton: +diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc +index ec38f473667d6..c1ed9570a7cfb 100644 +--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc ++++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc +@@ -44,6 +44,7 @@ + #include "components/prefs/pref_service.h" + #include "components/profile_metrics/browser_profile_type.h" + #include "components/url_formatter/url_formatter.h" ++#include "openbrowser/common/buildflags.h" + #include "content/public/browser/page_navigator.h" + #include "ui/base/accelerators/menu_label_accelerator_util.h" + #include "ui/base/dragdrop/drag_drop_types.h" +@@ -372,6 +373,10 @@ void BookmarkMenuDelegate::SetMenuStartIndex(const BookmarkParentFolder& folder, + std::u16string BookmarkMenuDelegate::GetTooltipText( + int id, + const gfx::Point& screen_loc) const { ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ // OpenBrowser: Disable URL tooltips in "All Bookmarks" menu (privacy/cleaner UI) ++ return std::u16string(); ++#else + auto i = menu_id_to_node_map_.find(id); + // Ignore queries about unknown items, e.g. the empty menu item. + if (i != menu_id_to_node_map_.end()) { +@@ -385,6 +390,7 @@ std::u16string BookmarkMenuDelegate::GetTooltipText( + } + } + return std::u16string(); ++#endif + } + + bool BookmarkMenuDelegate::IsTriggerableEvent(views::MenuItemView* menu, +diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc +index f8461a764aa85..f3acd022cbda6 100644 +--- a/chrome/browser/ui/views/status_bubble_views.cc ++++ b/chrome/browser/ui/views/status_bubble_views.cc +@@ -29,7 +29,12 @@ + #include "chrome/browser/ui/views/chrome_widget_sublevel.h" + #include "components/url_formatter/elide_url.h" + #include "components/url_formatter/url_formatter.h" ++#include "openbrowser/common/buildflags.h" + #include "third_party/skia/include/core/SkPath.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + #include "third_party/skia/include/core/SkRRect.h" + #include "third_party/skia/include/pathops/SkPathOps.h" + #include "ui/base/metadata/metadata_header_macros.h" +@@ -875,12 +880,19 @@ void StatusBubbleViews::SetStatus(const std::u16string& status_text) { + } + + void StatusBubbleViews::SetURL(const GURL& url) { +- url_ = url; ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(url); ++#else ++ const GURL& display_url = url; ++#endif ++ ++ url_ = display_url; + if (size_.IsEmpty()) { + return; // We have no bounds, don't attempt to show the popup. + } + +- if (url.is_empty() && status_text_.empty() && !popup_) { ++ if (display_url.is_empty() && status_text_.empty() && !popup_) { + return; + } + +@@ -888,7 +900,7 @@ void StatusBubbleViews::SetURL(const GURL& url) { + + // If we want to clear a displayed URL but there is a status still to + // display, display that status instead. +- if (url.is_empty() && !status_text_.empty()) { ++ if (display_url.is_empty() && !status_text_.empty()) { + url_text_ = std::u16string(); + if (IsFrameVisible()) { + view_->AnimateForText(status_text_); +@@ -899,11 +911,11 @@ void StatusBubbleViews::SetURL(const GURL& url) { + // Set Elided Text corresponding to the GURL object. + int text_width = static_cast( + size_.width() - (kShadowThickness + kTextHorizPadding) * 2 - 1); +- url_text_ = url_formatter::ElideUrl(url, GetFont(), text_width); ++ url_text_ = url_formatter::ElideUrl(display_url, GetFont(), text_width); + + // Get the width of the URL if the bubble width is the maximum size. + std::u16string full_size_elided_url = +- url_formatter::ElideUrl(url, GetFont(), GetMaxStatusBubbleWidth()); ++ url_formatter::ElideUrl(display_url, GetFont(), GetMaxStatusBubbleWidth()); + int url_width = GetWidthForURL(full_size_elided_url); + + // Get the width for the url if it is unexpanded. +@@ -912,15 +924,15 @@ void StatusBubbleViews::SetURL(const GURL& url) { + // Reset expansion state only when bubble is completely hidden. + if (view_->GetState() == StatusView::BubbleState::kHidden) { + is_expanded_ = false; +- url_text_ = url_formatter::ElideUrl(url, GetFont(), unexpanded_width); ++ url_text_ = url_formatter::ElideUrl(display_url, GetFont(), unexpanded_width); + SetBubbleWidth(unexpanded_width); + } + + if (IsFrameVisible()) { + // If bubble is not expanded & not empty, make it fit properly in the + // unexpanded bubble +- if (!is_expanded_ & !url.is_empty()) { +- url_text_ = url_formatter::ElideUrl(url, GetFont(), unexpanded_width); ++ if (!is_expanded_ & !display_url.is_empty()) { ++ url_text_ = url_formatter::ElideUrl(display_url, GetFont(), unexpanded_width); + SetBubbleWidth(unexpanded_width); + } + +@@ -928,9 +940,9 @@ void StatusBubbleViews::SetURL(const GURL& url) { + + // If bubble is already in expanded state, shift to adjust to new text + // size (shrinking or expanding). Otherwise delay. +- if (is_expanded_ && !url.is_empty()) { ++ if (is_expanded_ && !display_url.is_empty()) { + ExpandBubble(); +- } else if (url_formatter::FormatUrl(url).length() > url_text_.length()) { ++ } else if (url_formatter::FormatUrl(display_url).length() > url_text_.length()) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&StatusBubbleViews::ExpandBubble, +diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +index b7f8114c698d8..427c46af2af8a 100644 +--- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc ++++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +@@ -36,7 +36,12 @@ + #include "components/collaboration/public/messaging/message.h" + #include "components/strings/grit/components_strings.h" + #include "components/url_formatter/url_formatter.h" ++#include "openbrowser/common/buildflags.h" + #include "ui/accessibility/ax_enums.mojom.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + #include "ui/base/l10n/l10n_util.h" + #include "ui/base/metadata/metadata_header_macros.h" + #include "ui/base/metadata/metadata_impl_macros.h" +@@ -544,13 +549,20 @@ void TabHoverCardBubbleView::UpdateCardContent(const Tab* tab) { + alert_state_ = Tab::GetAlertStateToShow(tab_data.alert_state); + } + ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(domain_url); ++#else ++ const GURL& display_url = domain_url; ++#endif ++ + std::u16string domain; + bool is_filename = false; +- if (domain_url.SchemeIsFile()) { ++ if (display_url.SchemeIsFile()) { + is_filename = true; + domain = l10n_util::GetStringUTF16(IDS_HOVER_CARD_FILE_URL_SOURCE); + } else { +- if (domain_url.SchemeIsBlob()) { ++ if (display_url.SchemeIsBlob()) { + domain = l10n_util::GetStringUTF16(IDS_HOVER_CARD_BLOB_URL_SOURCE); + } else { + if (tab_data.should_display_url) { +@@ -558,7 +570,7 @@ void TabHoverCardBubbleView::UpdateCardContent(const Tab* tab) { + // card, but this scenario is very rare. Also, shrinking the card to + // remove the space would result in visual noise, so we keep it simple. + domain = url_formatter::FormatUrl( +- domain_url, ++ display_url, + url_formatter::kFormatUrlOmitDefaults | + url_formatter::kFormatUrlOmitHTTPS | + url_formatter::kFormatUrlOmitTrivialSubdomains | +diff --git a/chrome/browser/ui/webui/history/browsing_history_handler.cc b/chrome/browser/ui/webui/history/browsing_history_handler.cc +index c42124925de65..d1446ee97a670 100644 +--- a/chrome/browser/ui/webui/history/browsing_history_handler.cc ++++ b/chrome/browser/ui/webui/history/browsing_history_handler.cc +@@ -48,6 +48,11 @@ + #include "components/favicon/core/large_icon_service.h" + #include "components/favicon_base/favicon_url_parser.h" + #include "components/history_clusters/core/config.h" ++#include "openbrowser/common/buildflags.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + #include "components/history_clusters/core/features.h" + #include "components/history_clusters/core/history_clusters_prefs.h" + #include "components/history_embeddings/history_embeddings_features.h" +@@ -142,11 +147,18 @@ void GetDeviceNameAndType(const syncer::DeviceInfoTracker* tracker, + // Formats `entry`'s URL and title and adds them to `result`. + std::pair SetHistoryEntryUrlAndTitle( + const BrowsingHistoryService::HistoryEntry& entry) { ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(entry.url); ++#else ++ const GURL& display_url = entry.url; ++#endif ++ + bool using_url_as_the_title = false; + std::u16string title_to_set(entry.title); + if (entry.title.empty()) { + using_url_as_the_title = true; +- title_to_set = base::UTF8ToUTF16(entry.url.spec()); ++ title_to_set = base::UTF8ToUTF16(display_url.spec()); + } + + // Since the title can contain BiDi text, we need to mark the text as either +@@ -167,7 +179,7 @@ std::pair SetHistoryEntryUrlAndTitle( + title_to_set.resize(kShortTitleLength); + } + +- return std::make_tuple(entry.url.spec(), base::UTF16ToUTF8(title_to_set)); ++ return std::make_tuple(display_url.spec(), base::UTF16ToUTF8(title_to_set)); + } + + // Helper function to check if entry is present in local database (local-side +diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc +index 6161845cb7b47..b64846c84ab6b 100644 +--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc ++++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc +@@ -48,6 +48,11 @@ + #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom.h" + #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h" + #include "chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h" ++#include "openbrowser/common/buildflags.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif + #include "chrome/browser/ui/webui/webui_embedding_context.h" + #include "chrome/browser/undo/bookmark_undo_service_factory.h" + #include "chrome/grit/generated_resources.h" +@@ -365,7 +370,13 @@ side_panel::mojom::BookmarksTreeNodePtr ConstructMojoNode( + bookmark_merged_surface.GetChildren(sub_parent)); + } + } else { ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(node->url()); ++ mojo_node->url = display_url.spec(); ++#else + mojo_node->url = node->url().spec(); ++#endif + } + + return mojo_node; +@@ -877,9 +888,20 @@ void BookmarksPageHandler::BookmarkNodeMoved( + + void BookmarksPageHandler::BookmarkNodeChanged( + const bookmarks::BookmarkNode* node) { ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++ std::string url_str; ++ if (node->is_url()) { ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ GURL display_url = openbrowser::GetDisplayURLForInternal(node->url()); ++ url_str = display_url.spec(); ++#else ++ url_str = node->url().spec(); ++#endif ++ } ++ + page_->OnBookmarkNodeChanged(base::ToString(node->id()), + base::UTF16ToUTF8(node->GetTitle()), +- node->is_url() ? node->url().spec() : ""); ++ url_str); + } + + std::string GetFolderSidePanelIDForTesting( +diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn +index ec274ae97be13..41817245f3062 100644 +--- a/components/omnibox/browser/BUILD.gn ++++ b/components/omnibox/browser/BUILD.gn +@@ -345,6 +345,7 @@ static_library("browser") { + deps = [ + "//build:branding_buildflags", + "//components/bookmarks/browser", ++ "//openbrowser/common", + "//components/component_updater", + "//components/dom_distiller/core", + "//components/favicon/core", +diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc +index 2c9a990b5e4aa..8f79579d20384 100644 +--- a/components/omnibox/browser/location_bar_model_impl.cc ++++ b/components/omnibox/browser/location_bar_model_impl.cc +@@ -28,6 +28,12 @@ + #include "ui/gfx/vector_icon_types.h" + #include "url/origin.h" + ++#include "openbrowser/common/buildflags.h" ++ ++#if BUILDFLAG(OPENBROWSER_BUILD) ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++#endif ++ + #if (!BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !BUILDFLAG(IS_IOS) + #include "components/omnibox/browser/vector_icons.h" // nogncheck + #endif +@@ -93,6 +99,12 @@ std::u16string LocationBarModelImpl::GetFormattedURL( + + GURL url(GetURL()); + ++ // OpenBrowser: Rewrite chrome:// → openbrowser:// for display (Brave-style) ++ // This only affects what the user sees in the URL bar, not navigation ++#if BUILDFLAG(OPENBROWSER_BUILD) ++ url = openbrowser::GetDisplayURLForInternal(url); ++#endif ++ + #if BUILDFLAG(IS_IOS) + // On iOS, the blob: display URLs should be simply the domain name. However, + // url_formatter parses everything past blob: as path, not domain, so swap diff --git a/chromium/patches/settings_ui_changes.patch b/chromium/patches/settings_ui_changes.patch new file mode 100644 index 0000000..6bd72a0 --- /dev/null +++ b/chromium/patches/settings_ui_changes.patch @@ -0,0 +1,895 @@ +diff --git a/chrome/app/settings_chromium_strings.grdp b/chrome/app/settings_chromium_strings.grdp +index f5659b08ca0ed..9e3df4e5858d3 100644 +--- a/chrome/app/settings_chromium_strings.grdp ++++ b/chrome/app/settings_chromium_strings.grdp +@@ -1,10 +1,10 @@ + +- ++ + + + + +- Relaunch Chromium? ++ Relaunch OpenBrowser? + + + +@@ -18,26 +18,26 @@ + + + +- +- About Chromium ++ ++ About OpenBrowser + +- +- Get help with Chromium ++ ++ Get help with OpenBrowser + + + + +- +- Updating Chromium ++ ++ Updating OpenBrowser + +- +- Updating Chromium ($190%) ++ ++ Updating OpenBrowser ($190%) + +- +- Nearly up to date! Relaunch Chromium to finish updating. ++ ++ Nearly up to date! Relaunch OpenBrowser to finish updating. + +- +- Chromium is up to date ++ ++ OpenBrowser is up to date + + + +@@ -51,76 +51,76 @@ + + + +- Chromium can't check your passwords. Try checking your internet connection. ++ OpenBrowser can't check your passwords. Try checking your internet connection. + + +- Chromium can check your passwords when you sign in with your Google Account ++ OpenBrowser can check your passwords when you sign in with your Google Account + + +- No saved passwords. Chromium can check your passwords when you save them. ++ No saved passwords. OpenBrowser can check your passwords when you save them. + + +- Chromium can't check your passwords. Try again after 24 hours or <a href="$1" target="_blank">check passwords in your Google Account</a>. ++ OpenBrowser can't check your passwords. Try again after 24 hours or <a href="$1" target="_blank">check passwords in your Google Account</a>. + + +- Chromium can't check your passwords. Try again after 24 hours. ++ OpenBrowser can't check your passwords. Try again after 24 hours. + + +- Chromium can't check your passwords. Try again later. ++ OpenBrowser can't check your passwords. Try again later. + + +- Chromium will notify you when you sign in with a compromised password ++ OpenBrowser will notify you when you sign in with a compromised password + + +- To check if your passwords are safe from data breaches and other security issues, <a target='_blank' href='$1'>sign in to Chromium</a>. ++ To check if your passwords are safe from data breaches and other security issues, <a target='_blank' href='$1'>sign in to OpenBrowser</a>. + + +- To check if your other passwords are safe from data breaches and other security issues, <a target='_blank' href='$1'>sign in to Chromium</a>. ++ To check if your other passwords are safe from data breaches and other security issues, <a target='_blank' href='$1'>sign in to OpenBrowser</a>. + + +- Weak passwords are easy to guess. Let Chromium <a target='_blank' href='$1'>create and remember strong passwords for you</a>. ++ Weak passwords are easy to guess. Let OpenBrowser <a target='_blank' href='$1'>create and remember strong passwords for you</a>. + +- +- If so, please edit your saved password in Chromium so it matches your new password. ++ ++ If so, please edit your saved password in OpenBrowser so it matches your new password. + + + + +- Chromium understands forms better and can autofill them faster for you ++ OpenBrowser understands forms better and can autofill them faster for you + + +-Chromium understands forms better and can autofill them faster for you. This setting is on. ++OpenBrowser understands forms better and can autofill them faster for you. This setting is on. + + +-Chromium understands forms better and can autofill them faster for you. This setting is off. ++OpenBrowser understands forms better and can autofill them faster for you. This setting is off. + +- +- Chromium understands forms better and can autofill them faster for you ++ ++ OpenBrowser understands forms better and can autofill them faster for you + +- +- Later, Chromium can ask if you want to use saved info to autofill forms for you ++ ++ Later, OpenBrowser can ask if you want to use saved info to autofill forms for you + + + + + +- Chromium is your default browser ++ OpenBrowser is your default browser + +- +- Thanks for choosing Chromium as your default browser! ++ ++ Thanks for choosing OpenBrowser as your default browser! + + +- Make Chromium the default browser ++ Make OpenBrowser the default browser + +- +- You can use Chromium anytime you click links in messages, documents, and other apps ++ ++ You can use OpenBrowser anytime you click links in messages, documents, and other apps + +- +- Make Chromium the default browser and pin to the taskbar ++ ++ Make OpenBrowser the default browser and pin to the taskbar + + +- Chromium cannot determine or set the default browser ++ OpenBrowser cannot determine or set the default browser + + + +@@ -129,8 +129,8 @@ Chromium understands forms better and can autofill them faster for you. This set + + + +- +- This is a secondary installation of Chromium, and cannot be made your default browser. ++ ++ This is a secondary installation of OpenBrowser, and cannot be made your default browser. + + + +@@ -138,347 +138,347 @@ Chromium understands forms better and can autofill them faster for you. This set + + + +- Chromium preloads pages you're likely to visit, so that they load more quickly when you visit them ++ OpenBrowser preloads pages you're likely to visit, so that they load more quickly when you visit them + + +- Chromium preloads even more pages that you're likely to visit, so that they load more quickly when you visit them ++ OpenBrowser preloads even more pages that you're likely to visit, so that they load more quickly when you visit them + + +- When a site asks to privately preload links on their page, Chromium uses Google servers. This hides your identity from the preloaded site, but Google learns what sites get preloaded. ++ When a site asks to privately preload links on their page, OpenBrowser uses Google servers. This hides your identity from the preloaded site, but Google learns what sites get preloaded. + + +- If you allow cookies, Chromium may use them when preloading ++ If you allow cookies, OpenBrowser may use them when preloading + + + + +- To fix spelling errors, Chromium sends the text you type in text fields to Google ++ To fix spelling errors, OpenBrowser sends the text you type in text fields to Google + + +- To apply your changes, relaunch Chromium ++ To apply your changes, relaunch OpenBrowser + + + + +- Allow Chromium sign-in ++ Allow OpenBrowser sign-in + + +- By turning this off, you can sign in to Google sites like Gmail without signing in to Chromium ++ By turning this off, you can sign in to Google sites like Gmail without signing in to OpenBrowser + + +- Shows prompts to sign in to Chromium ++ Shows prompts to sign in to OpenBrowser + + + + + +- Open PDFs in Chromium ++ Open PDFs in OpenBrowser + + +- To use your camera, give Chromium access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> ++ To use your camera, give OpenBrowser access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> + + +- To use your microphone, give Chromium access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> ++ To use your microphone, give OpenBrowser access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> + + +- To use your location, give Chromium access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> ++ To use your location, give OpenBrowser access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> + + +- To use your camera on these sites, give Chromium access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> ++ To use your camera on these sites, give OpenBrowser access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> + + +- To use your location on these sites, give Chromium access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> ++ To use your location on these sites, give OpenBrowser access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> + + +- To use your microphone on these sites, give Chromium access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> ++ To use your microphone on these sites, give OpenBrowser access in <a href="#" id="openSystemSettingsLink" >system settings</a></a> + + + + +- Sites will probably work as expected. You'll be signed out of most sites when you close all Chromium windows, except your Google Account if you're signed in to Chromium. ++ Sites will probably work as expected. You'll be signed out of most sites when you close all OpenBrowser windows, except your Google Account if you're signed in to OpenBrowser. + + +- Always delete site data from your device when you close Chromium ++ Always delete site data from your device when you close OpenBrowser + + + + +- Review key privacy and security controls in Chromium ++ Review key privacy and security controls in OpenBrowser + + +- Checks URLs with a list of unsafe sites stored in Chromium ++ Checks URLs with a list of unsafe sites stored in OpenBrowser + + +- If a site tries to steal your password, or when you download a harmful file, Chromium may also send URLs, including bits of page content, to Safe Browsing ++ If a site tries to steal your password, or when you download a harmful file, OpenBrowser may also send URLs, including bits of page content, to Safe Browsing + + +- Chromium gives you more control over the ads you see and limits what sites can learn about you when they show you personalized ads ++ OpenBrowser gives you more control over the ads you see and limits what sites can learn about you when they show you personalized ads + + +- Choose whether to include Chromium history for more personalized experiences in Google services ++ Choose whether to include OpenBrowser history for more personalized experiences in Google services + + +- If you also save your bookmarks in your Google Account, you can track product prices in Chromium and get notified when the price drops ++ If you also save your bookmarks in your Google Account, you can track product prices in OpenBrowser and get notified when the price drops + + +- If you also share Chromium usage reports, those reports include the URLs you visit ++ If you also share OpenBrowser usage reports, those reports include the URLs you visit + + + + +- Your interests as estimated by Chromium ++ Your interests as estimated by OpenBrowser + + +- Ad measurement allows sites you visit to request information from Chromium that helps the site measure the performance of their ads. Ad measurement restricts cross-site tracking by transferring as little information as possible between sites. ++ Ad measurement allows sites you visit to request information from OpenBrowser that helps the site measure the performance of their ads. Ad measurement restricts cross-site tracking by transferring as little information as possible between sites. + + + + +- To protect your data, let Chromium remove permissions from sites you haven't visited recently. Doesn't stop notifications. ++ To protect your data, let OpenBrowser remove permissions from sites you haven't visited recently. Doesn't stop notifications. + + +- To protect your data, let Chromium remove permissions from sites you haven't visited recently. ++ To protect your data, let OpenBrowser remove permissions from sites you haven't visited recently. + + + + +- Keeps you safe on Chromium and may be used to improve your security in other Google apps when you are signed in ++ Keeps you safe on OpenBrowser and may be used to improve your security in other Google apps when you are signed in + + +- Checks URLs with a list of unsafe sites stored in Chromium. If a site tries to steal your password, or when you download a harmful file, Chromium may also send URLs, including bits of page content, to Safe Browsing. ++ Checks URLs with a list of unsafe sites stored in OpenBrowser. If a site tries to steal your password, or when you download a harmful file, OpenBrowser may also send URLs, including bits of page content, to Safe Browsing. + + +- Warns you about dangerous sites, even ones Google didn't know about before, by analyzing more data from sites than standard protection. You can choose to skip Chromium warnings. ++ Warns you about dangerous sites, even ones Google didn't know about before, by analyzing more data from sites than standard protection. You can choose to skip OpenBrowser warnings. + + +- Learn more about <a href="#" id="enhancedProtectionLearnMoreLink" on-click="onEnhancedProtectionLearnMoreClick_">how Chromium keeps your data private</a></a> ++ Learn more about <a href="#" id="enhancedProtectionLearnMoreLink" on-click="onEnhancedProtectionLearnMoreClick_">how OpenBrowser keeps your data private</a></a> + + +- Make it harder for people with access to your internet traffic to see which sites you visit. Chromium uses a secure connection to look up a site's IP address in the DNS (Domain Name System). ++ Make it harder for people with access to your internet traffic to see which sites you visit. OpenBrowser uses a secure connection to look up a site's IP address in the DNS (Domain Name System). + + + + +- This will delete 1 item from this device. To retrieve your data later, sign in to Chromium as $1foo@example.com. ++ This will delete 1 item from this device. To retrieve your data later, sign in to OpenBrowser as $1foo@example.com. + + +- This will delete $166 items from this device. To retrieve your data later, sign in to Chromium as $2foo@example.com. ++ This will delete $166 items from this device. To retrieve your data later, sign in to OpenBrowser as $2foo@example.com. + + +- This will delete your browsing data from this device. To retrieve your data later, sign in to Chromium as $1foo@example.com. ++ This will delete your browsing data from this device. To retrieve your data later, sign in to OpenBrowser as $1foo@example.com. + + + +- Customize your Chromium profile ++ Customize your OpenBrowser profile + + +- Name your Chromium profile ++ Name your OpenBrowser profile + + +- +- Sync and personalize Chromium across your devices ++ ++ Sync and personalize OpenBrowser across your devices + +- +- To get your passwords and more on all your devices, sign in to Chromium ++ ++ To get your passwords and more on all your devices, sign in to OpenBrowser + +- +- To get your passwords, bookmarks, and more on all your devices, sign in to Chromium ++ ++ To get your passwords, bookmarks, and more on all your devices, sign in to OpenBrowser + + +- Your Chromium ++ Your OpenBrowser + + + +- You can manage your signed-in Google Accounts. Your Google Accounts are used for Chromium browser, Play Store, Gmail, and more. If you want to add an account for someone else, like a family member, add a new person to your $1Chromebook instead. <a>Learn more</a> ++ You can manage your signed-in Google Accounts. Your Google Accounts are used for OpenBrowser browser, Play Store, Gmail, and more. If you want to add an account for someone else, like a family member, add a new person to your $1Chromebook instead. <a>Learn more</a> + + +- +- Sign in to Chromium when you sign in to other Google services ++ ++ Sign in to OpenBrowser when you sign in to other Google services + +- +- When signing into Google services like Gmail or Youtube with $1foo@example.com, you can automatically sign in to Chromium with the same account ++ ++ When signing into Google services like Gmail or Youtube with $1foo@example.com, you can automatically sign in to OpenBrowser with the same account + +- +- Make Chromium your own ++ ++ Make OpenBrowser your own + + + + +- For added security, Chromium will encrypt your data. ++ For added security, OpenBrowser will encrypt your data. + + +- Sign out of Chromium? ++ Sign out of OpenBrowser? + + +- When you type in the address bar or search box, Chromium sends what you type to your default search engine to get better suggestions. This is off in Incognito. ++ When you type in the address bar or search box, OpenBrowser sends what you type to your default search engine to get better suggestions. This is off in Incognito. + + +- When you type in the address bar or search box, Chromium sends what you type to your organization's search, AI, and agent tools to get suggestions. ++ When you type in the address bar or search box, OpenBrowser sends what you type to your organization's search, AI, and agent tools to get suggestions. + +- +- Sign in to sync and personalize Chromium across your devices ++ ++ Sign in to sync and personalize OpenBrowser across your devices + + +- To get personalization, include Chromium in Web & App Activity ++ To get personalization, include OpenBrowser in Web & App Activity + + +- To get personalization and other features, include Chromium in Web & App Activity and linked Google services ++ To get personalization and other features, include OpenBrowser in Web & App Activity and linked Google services + + +- Link Chromium and other Google services for personalization and other purposes ++ Link OpenBrowser and other Google services for personalization and other purposes + + +- To use and save Chromium data in your Google Account, enter your passphrase ++ To use and save OpenBrowser data in your Google Account, enter your passphrase + + +- To use and save Chromium data in your Google Account, verify it's you ++ To use and save OpenBrowser data in your Google Account, verify it's you + + +- To use and save Chromium data in your Google Account, update Chromium ++ To use and save OpenBrowser data in your Google Account, update OpenBrowser + + +- Verify it's you to use and save Chromium data in your account, $1elisa.beckett@gmail.com ++ Verify it's you to use and save OpenBrowser data in your account, $1elisa.beckett@gmail.com + + +- Enter your passphrase to use and save Chromium data in your account, $1foo@example.com ++ Enter your passphrase to use and save OpenBrowser data in your account, $1foo@example.com + + +- Sign out of Chromium ++ Sign out of OpenBrowser + +- +- Chromium data in your account ++ ++ OpenBrowser data in your account + + +- Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the Chromium data in your Google Account. Payment methods and addresses from Google Pay won’t be encrypted. Browsing history from Chromium won’t sync. ++ Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the OpenBrowser data in your Google Account. Payment methods and addresses from Google Pay won’t be encrypted. Browsing history from OpenBrowser won’t sync. + + +- Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you’ll need to <a href="$1" target="_blank"><a href="$1" target="_blank">delete the Chromium data in your account</a></a>. ++ Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you’ll need to <a href="$1" target="_blank"><a href="$1" target="_blank">delete the OpenBrowser data in your account</a></a>. + + + +- Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the Chromium data in your Google Account. Addresses and any data saved in Google Wallet won’t be encrypted by your passphrase. Browsing history from Chromium won’t sync. ++ Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the OpenBrowser data in your Google Account. Addresses and any data saved in Google Wallet won’t be encrypted by your passphrase. Browsing history from OpenBrowser won’t sync. + + + +- If you forgot your passphrase or want to change this setting, <a href="$1" target="_blank"><a href="$1" target="_blank">delete the Chromium data in your account</a></a> ++ If you forgot your passphrase or want to change this setting, <a href="$1" target="_blank"><a href="$1" target="_blank">delete the OpenBrowser data in your account</a></a> + + + + +- To help improve these features, Chromium sends your interactions with them to Google. This data may be read, processed, and annotated by human reviewers. ++ To help improve these features, OpenBrowser sends your interactions with them to Google. This data may be read, processed, and annotated by human reviewers. + + + + +- Chromium frees up memory from inactive tabs. This gives active tabs and other apps more computer resources and keeps Chromium fast. Your inactive tabs automatically become active again when you go back to them. <a href="$1" target="_blank" id="learn-more" aria-description="$2">Learn more about Memory Saver</a> ++ OpenBrowser frees up memory from inactive tabs. This gives active tabs and other apps more computer resources and keeps OpenBrowser fast. Your inactive tabs automatically become active again when you go back to them. <a href="$1" target="_blank" id="learn-more" aria-description="$2">Learn more about Memory Saver</a> + + +- Chromium conserves battery power by limiting background activity and visual effects, such as smooth scrolling and video frame rates. <a href="$1" target="_blank" id="learn-more" aria-description="$2">Learn more about Energy Saver</a> ++ OpenBrowser conserves battery power by limiting background activity and visual effects, such as smooth scrolling and video frame rates. <a href="$1" target="_blank" id="learn-more" aria-description="$2">Learn more about Energy Saver</a> + + +- Chromium preloads pages which makes browsing and searching faster. <a href="$1" target="_blank" id="learn-more" aria-description="$2">Learn more about preload pages</a> ++ OpenBrowser preloads pages which makes browsing and searching faster. <a href="$1" target="_blank" id="learn-more" aria-description="$2">Learn more about preload pages</a> + + + + + +- This language is used to display menus, settings, alerts, and other text in Chromium ++ This language is used to display menus, settings, alerts, and other text in OpenBrowser + + +- Display Chromium in this language ++ Display OpenBrowser in this language + + + + + + +- Continue running background apps when Chromium is closed ++ Continue running background apps when OpenBrowser is closed + + + + + +- Help make Chromium better by reporting the <a is="action-link" target="_blank">current settings</a> ++ Help make OpenBrowser better by reporting the <a is="action-link" target="_blank">current settings</a> + + + +- +- Chromium regularly checks to make sure your browser has the safest settings. We'll let you know if anything needs your review. ++ ++ OpenBrowser regularly checks to make sure your browser has the safest settings. We'll let you know if anything needs your review. + + +- Chromium found some safety recommendations for your review ++ OpenBrowser found some safety recommendations for your review + + +- Chromium will let you know if anything needs your review ++ OpenBrowser will let you know if anything needs your review + +- +- Chromium update ++ ++ OpenBrowser update + +- +- Chromium update ++ ++ OpenBrowser update + + +- Chromium can check your passwords when you save them ++ OpenBrowser can check your passwords when you save them + + +- Learn how Chromium keeps you safe ++ Learn how OpenBrowser keeps you safe + + +- Chromium's safety tools ++ OpenBrowser's safety tools + + +- With <a href="$1" target="_blank">tools from Chromium</a>, you can browse safely and stay in control ++ With <a href="$1" target="_blank">tools from OpenBrowser</a>, you can browse safely and stay in control + + +- Chromium Incognito ++ OpenBrowser Incognito + + +- <a href="$1" target="_blank">Chromium warns you</a> about unsafe sites and downloads ++ <a href="$1" target="_blank">OpenBrowser warns you</a> about unsafe sites and downloads + + + +- Chromium is out of date ++ OpenBrowser is out of date + + +- Chromium is up to date ++ OpenBrowser is up to date + + +- +- Go to About Chromium page ++ ++ Go to About OpenBrowser page + +- +- Relaunch Chromium ++ ++ Relaunch OpenBrowser + + +- You haven't visited recently. Chromium removed $1location. ++ You haven't visited recently. OpenBrowser removed $1location. + + +- You haven't visited recently. Chromium removed $1location, $2notifications. ++ You haven't visited recently. OpenBrowser removed $1location, $2notifications. + + +- You haven't visited recently. Chromium removed $1location, $2notifications, $3camera. ++ You haven't visited recently. OpenBrowser removed $1location, $2notifications, $3camera. + + +- You haven't visited recently. Chromium removed $1location, $2notifications, and $32 more. ++ You haven't visited recently. OpenBrowser removed $1location, $2notifications, and $32 more. + + +- Dangerous site. Chromium removed notifications. ++ Dangerous site. OpenBrowser removed notifications. + + + + +- Chromium upgrades insecure connections to HTTPS automatically when possible ++ OpenBrowser upgrades insecure connections to HTTPS automatically when possible + + +- Chromium will try to upgrade navigations to HTTPS ++ OpenBrowser will try to upgrade navigations to HTTPS + + +- Chromium will warn you before loading any site using an insecure connection ++ OpenBrowser will warn you before loading any site using an insecure connection + + +- When browsing in Incognito mode, Chromium will warn you before loading a site using an insecure connection ++ When browsing in Incognito mode, OpenBrowser will warn you before loading a site using an insecure connection + + +- When HTTPS isn't available, Chromium will use an insecure connection without warning you ++ When HTTPS isn't available, OpenBrowser will use an insecure connection without warning you + + +diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp +index 7edfde1f4fd6c..e72339448cda0 100644 +--- a/chrome/app/settings_strings.grdp ++++ b/chrome/app/settings_strings.grdp +@@ -340,7 +340,7 @@ + Settings + + +- Settings - $1About Chromium ++ Settings - $1About OpenBrowser + + + Subpage button +@@ -759,7 +759,7 @@ + + Are you sure you want to delete this passkey? + +- ++ + Can't delete passkey + + +@@ -1756,7 +1756,7 @@ + Passwords + + +- Password check is not available in Chromium ++ Password check is not available in OpenBrowser + + + Safe Browsing is on and protecting you from harmful sites and downloads +@@ -3644,8 +3644,8 @@ + + + +- +- You and Google ++ ++ You and OpenBrowser + + + Google Profile photo +@@ -3654,7 +3654,7 @@ + + Sign in + +- ++ + Verify it's you + + +diff --git a/chrome/app/shared_settings_strings.grdp b/chrome/app/shared_settings_strings.grdp +index 35ef542fa88ef..d8fb93e1094af 100644 +--- a/chrome/app/shared_settings_strings.grdp ++++ b/chrome/app/shared_settings_strings.grdp +@@ -239,7 +239,7 @@ + + Enhanced spell check + +- ++ + Help improve Chrome's features and performance + + +@@ -439,7 +439,7 @@ + + Checking for updates + +- ++ + You reverted to a previous version of ChromeOS. To get updates, wait until the next version is available. + + +diff --git a/chrome/app/theme/chromium/product_logo_animation.svg b/chrome/app/theme/chromium/product_logo_animation.svg +index 3b0ebc65206f6..b45170fbb0c74 100644 +--- a/chrome/app/theme/chromium/product_logo_animation.svg ++++ b/chrome/app/theme/chromium/product_logo_animation.svg +@@ -1,43 +1,4 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ ++ ++ + +diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html +index 5069802bf7a17..f81ec663e9dfe 100644 +--- a/chrome/browser/resources/settings/about_page/about_page.html ++++ b/chrome/browser/resources/settings/about_page/about_page.html +@@ -47,11 +47,16 @@ + + +

+
+diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html +index 436249d603479..f74d0eeec59e2 100644 +--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html ++++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html +@@ -177,7 +177,7 @@ + + +- ++ + $i18n{aboutPageTitle} + + +diff --git a/chrome/browser/ui/webui/current_channel_logo.cc b/chrome/browser/ui/webui/current_channel_logo.cc +index d9fca84f38db0..c1d236bbbbd6a 100644 +--- a/chrome/browser/ui/webui/current_channel_logo.cc ++++ b/chrome/browser/ui/webui/current_channel_logo.cc +@@ -34,4 +34,9 @@ int CurrentChannelLogoResourceId() { + return -1; + } + ++int CurrentChannelLogoDarkResourceId() { ++ // For dark mode, always return the white logo ++ return IDR_PRODUCT_LOGO_32_WHITE; ++} ++ + } // namespace webui +diff --git a/chrome/browser/ui/webui/current_channel_logo.h b/chrome/browser/ui/webui/current_channel_logo.h +index 8f109b4d2320d..ebfe0b970e790 100644 +--- a/chrome/browser/ui/webui/current_channel_logo.h ++++ b/chrome/browser/ui/webui/current_channel_logo.h +@@ -10,6 +10,9 @@ namespace webui { + // Returns the resource id of the current channel logo. + int CurrentChannelLogoResourceId(); + ++// Returns the resource id of the current channel logo for dark mode (white version). ++int CurrentChannelLogoDarkResourceId(); ++ + } // namespace webui + + #endif // CHROME_BROWSER_UI_WEBUI_CURRENT_CHANNEL_LOGO_H_ +diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc +index 933bb620d795d..0545dff89469b 100644 +--- a/chrome/browser/ui/webui/theme_source.cc ++++ b/chrome/browser/ui/webui/theme_source.cc +@@ -128,6 +128,8 @@ void ThemeSource::StartDataRequest( + int resource_id = -1; + if (parsed_path == "current-channel-logo") { + resource_id = webui::CurrentChannelLogoResourceId(); ++ } else if (parsed_path == "current-channel-logo-dark") { ++ resource_id = webui::CurrentChannelLogoDarkResourceId(); + } else { + resource_id = ResourcesUtil::GetThemeResourceId(parsed_path); + } +diff --git a/components/components_chromium_strings.grd b/components/components_chromium_strings.grd +index dc9a4c1e54c6a..6025f62aaa97f 100644 +--- a/components/components_chromium_strings.grd ++++ b/components/components_chromium_strings.grd +@@ -271,8 +271,8 @@ + + + +- +- Chromium logo ++ ++ OpenBrowser logo + + + +diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +index d95689b8b1196..031f10294a8e8 100644 +--- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts ++++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +@@ -15,8 +15,8 @@ export function getHtml(this: CrDrawerElement) { + + + ++ srcset="chrome://theme/current-channel-logo-dark@1x 1x, ++ chrome://theme/current-channel-logo-dark@2x 2x"> + + + ++ srcset="chrome://theme/current-channel-logo-dark@1x 1x, ++ chrome://theme/current-channel-logo-dark@2x 2x"> + + + ++ ++ ++ + + diff --git a/chromium/patches/ui/theme_and_ui_changes.patch b/chromium/patches/ui/theme_and_ui_changes.patch new file mode 100644 index 0000000..48661e8 --- /dev/null +++ b/chromium/patches/ui/theme_and_ui_changes.patch @@ -0,0 +1,1250 @@ +diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h +index 59296a7cb076a..c349c59837fe9 100644 +--- a/chrome/browser/ui/color/chrome_color_id.h ++++ b/chrome/browser/ui/color/chrome_color_id.h +@@ -657,6 +657,7 @@ + E_CPONLY(kColorSearchboxResultsForeground) \ + E_CPONLY(kColorSearchboxResultsForegroundDimmed) \ + E_CPONLY(kColorSearchboxResultsIcon) \ ++ E_CPONLY(kColorSearchboxResultsIconContainerBackground) \ + E_CPONLY(kColorSearchboxResultsIconFocusedOutline) \ + E_CPONLY(kColorSearchboxResultsIconSelected) \ + E_CPONLY(kColorSearchboxResultsUrl) \ +diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc +index d6f02fceb7ee8..9446c65b4d2cf 100644 +--- a/chrome/browser/ui/color/chrome_color_mixer.cc ++++ b/chrome/browser/ui/color/chrome_color_mixer.cc +@@ -192,9 +192,9 @@ void AddChromeColorMixer(ui::ColorProvider* provider, + mixer[kColorExtensionsMenuContainerBackground] = {ui::kColorSysSurface3}; + mixer[kColorFeatureFirstRunInfoContainerBackground] = {ui::kColorSysSurface3}; + mixer[kColorFeatureFirstRunIconColor] = {ui::kColorSysOnSurfaceSubtle}; +- mixer[kColorFeaturePromoBubbleBackground] = {gfx::kGoogleBlue700}; ++ mixer[kColorFeaturePromoBubbleBackground] = {dark_mode ? SK_ColorWHITE : SK_ColorBLACK}; + mixer[kColorFeaturePromoBubbleButtonBorder] = {gfx::kGoogleGrey300}; +- mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {gfx::kGoogleBlue300}; ++ mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {dark_mode ? SK_ColorBLACK : SK_ColorWHITE}; + mixer[kColorFeaturePromoBubbleDefaultButtonBackground] = { + kColorFeaturePromoBubbleForeground}; + mixer[kColorFeaturePromoBubbleDefaultButtonForeground] = { +diff --git a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc +index b2b1a40d80524..18cf4a075b8f2 100644 +--- a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc +@@ -53,7 +53,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + ui::kColorSysStateHoverOnSubtle}; + mixer[kColorNewTabPageButtonForeground] = {ui::kColorSysOnTonalContainer}; + +- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; ++ mixer[kColorComposeboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; + mixer[kColorComposeboxFont] = { + dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) +@@ -103,8 +105,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + : SkColorSetRGB(0xAD, 0xAF, 0xB8)}; + mixer[kColorComposeboxFileChipBackground] = {kColorSysSurface3_Light}; + mixer[kColorComposeboxFileChipFaviconBackground] = {kColorSysSurface_Light}; +- mixer[kColorComposeboxFileChipText] = { +- SkColorSetRGB(0x1F, 0x1F, 0x1F)}; ++ mixer[kColorComposeboxFileChipText] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : SkColorSetRGB(0x1F, 0x1F, 0x1F)}; + mixer[kColorComposeboxPdfChipIcon] = { + dark_mode ? SkColorSetRGB(0xAD, 0xAF, 0xB8) + : SkColorSetRGB(0x56, 0x59, 0x5E)}; +@@ -219,12 +222,20 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + ui::kColorSysOnPrimary}; + if (base::FeatureList::IsEnabled(ntp_features::kRealboxCr23Theming)) { + // Steady state theme colors. +- mixer[kColorSearchboxBackground] = {kColorToolbarBackgroundSubtleEmphasis}; ++ mixer[kColorSearchboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(kColorToolbarBackgroundSubtleEmphasis)}; ++ mixer[kColorSearchboxPlaceholder] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxTextDimmed)}; ++ mixer[kColorSearchboxSearchIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxLensVoiceIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(ui::kColorSysPrimary)}; + mixer[kColorSearchboxBackgroundHovered] = { + kColorToolbarBackgroundSubtleEmphasisHovered}; +- mixer[kColorSearchboxPlaceholder] = {kColorOmniboxTextDimmed}; +- mixer[kColorSearchboxSearchIconBackground] = {kColorOmniboxResultsIcon}; +- mixer[kColorSearchboxLensVoiceIconBackground] = {ui::kColorSysPrimary}; + mixer[kColorSearchboxSelectionBackground] = { + kColorOmniboxSelectionBackground}; + mixer[kColorSearchboxSelectionForeground] = { +@@ -235,42 +246,56 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + kColorOmniboxAnswerIconGM3Background}; + mixer[kColorSearchboxAnswerIconForeground] = { + kColorOmniboxAnswerIconGM3Foreground}; +- mixer[kColorSearchboxForeground] = {kColorOmniboxText}; + mixer[kColorSearchboxResultsActionChip] = {ui::kColorSysTonalOutline}; + mixer[kColorSearchboxResultsActionChipIcon] = {ui::kColorSysPrimary}; + mixer[kColorSearchboxResultsActionChipFocusOutline] = { + ui::kColorSysStateFocusRing}; +- mixer[kColorSearchboxResultsBackgroundHovered] = { +- kColorOmniboxResultsBackgroundHovered}; +- mixer[kColorSearchboxResultsButtonHover] = { +- kColorOmniboxResultsButtonInkDropRowHovered}; +- mixer[kColorSearchboxResultsDimSelected] = { +- kColorOmniboxResultsTextDimmedSelected}; + mixer[kColorSearchboxResultsFocusIndicator] = { + kColorOmniboxResultsFocusIndicator}; +- mixer[kColorSearchboxResultsForeground] = {kColorOmniboxText}; +- mixer[kColorSearchboxResultsForegroundDimmed] = {kColorOmniboxTextDimmed}; +- mixer[kColorSearchboxResultsIcon] = {kColorOmniboxResultsIcon}; +- mixer[kColorSearchboxResultsIconSelected] = {kColorOmniboxResultsIcon}; + mixer[kColorSearchboxResultsIconFocusedOutline] = { + kColorOmniboxResultsButtonIconSelected}; +- mixer[kColorSearchboxResultsUrl] = {kColorOmniboxResultsUrl}; +- mixer[kColorSearchboxResultsUrlSelected] = { +- kColorOmniboxResultsUrlSelected}; ++ ++ mixer[kColorSearchboxForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(kColorOmniboxText)}; ++ mixer[kColorSearchboxResultsBackgroundHovered] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsBackgroundHovered)}; ++ mixer[kColorSearchboxResultsButtonHover] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsButtonInkDropRowHovered)}; ++ mixer[kColorSearchboxResultsDimSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsTextDimmedSelected)}; ++ mixer[kColorSearchboxResultsForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(kColorOmniboxText)}; ++ mixer[kColorSearchboxResultsForegroundDimmed] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxTextDimmed)}; ++ mixer[kColorSearchboxResultsIcon] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxResultsIconContainerBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxResultsIconSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxResultsUrl] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : ui::ColorTransform(kColorOmniboxResultsUrl)}; ++ mixer[kColorSearchboxResultsUrlSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : ui::ColorTransform(kColorOmniboxResultsUrlSelected)}; + mixer[kColorSearchboxShadow] = + ui::SetAlpha(gfx::kGoogleGrey900, + (dark_mode ? /* % opacity */ 0.32 : 0.1) * SK_AlphaOPAQUE); + +- // This determines weather the realbox expanded state background in dark +- // mode will match the omnibox or not. +- if (dark_mode && +- !ntp_features::kNtpRealboxCr23ExpandedStateBgMatchesOmnibox.Get()) { +- mixer[kColorSearchboxResultsBackground] = { +- kColorToolbarBackgroundSubtleEmphasis}; +- } else { +- mixer[kColorSearchboxResultsBackground] = { +- kColorOmniboxResultsBackground}; +- } ++ // Use base container color for searchbox results background in dark mode, omnibox color in light mode ++ mixer[kColorSearchboxResultsBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(kColorOmniboxResultsBackground)}; + } + + /* NewTabFooter */ +diff --git a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc +index 8d99d0d5e526e..0a06f2f6d7a0d 100644 +--- a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc ++++ b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc +@@ -27,8 +27,9 @@ void AddMaterialTabStripColorMixer(ui::ColorProvider* provider, + + // TODO(crbug.com/40883407): Validate final mappings for ChromeRefresh23 + // color. ++ const bool dark_mode = key.color_mode == ui::ColorProviderKey::ColorMode::kDark; + ui::ColorMixer& mixer = provider->AddMixer(); +- mixer[kColorTabBackgroundActiveFrameActive] = {ui::kColorSysBase}; ++ mixer[kColorTabBackgroundActiveFrameActive] = {dark_mode ? ui::kColorSysBaseContainer : ui::kColorSysSurface}; + mixer[kColorTabBackgroundActiveFrameInactive] = { + kColorTabBackgroundActiveFrameActive}; + +diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +index 558cc275c8847..350f052b92aef 100644 +--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +@@ -314,7 +314,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + ui::SelectBasedOnDarkInput(kColorNewTabPageAddShortcutBackground, + SK_ColorWHITE, gfx::kGoogleGrey900); + +- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; ++ mixer[kColorComposeboxBackground] = {dark_mode ? ui::kColorSysBaseContainer : SK_ColorWHITE}; + mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; + mixer[kColorComposeboxFont] = { + dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) +@@ -400,15 +400,28 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + SkColorSetRGB(0xD3, 0xE3, 0xFD)}; + mixer[kColorSearchboxAnswerIconForeground] = { + SkColorSetRGB(0x04, 0x1E, 0x49)}; +- mixer[kColorSearchboxBackground] = {SK_ColorWHITE}; +- mixer[kColorSearchboxBackgroundHovered] = {SK_ColorWHITE}; ++ mixer[kColorSearchboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxBackgroundHovered] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(SK_ColorBLACK)}; ++ mixer[kColorSearchboxPlaceholder] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxLensVoiceIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorSearchboxBorder] = { + key.contrast_mode == ui::ColorProviderKey::ContrastMode::kHigh + ? kColorLocationBarBorder + : gfx::kGoogleGrey300}; +- mixer[kColorSearchboxForeground] = {SK_ColorBLACK}; +- mixer[kColorSearchboxPlaceholder] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsBackground] = {SK_ColorWHITE}; + mixer[kColorSearchboxResultsBackgroundHovered] = + ui::SetAlpha(gfx::kGoogleGrey900, + /* 10% opacity */ 0.1 * SK_AlphaOPAQUE); +@@ -420,16 +433,39 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + SkColorSetRGB(0x0B, 0x57, 0xD0)}; + mixer[kColorSearchboxResultsActionChipFocusOutline] = { + SkColorSetRGB(0x0B, 0x57, 0xD0)}; +- mixer[kColorSearchboxResultsDimSelected] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsFocusIndicator] = {gfx::kGoogleBlue600}; +- mixer[kColorSearchboxResultsForeground] = {SK_ColorBLACK}; +- mixer[kColorSearchboxResultsForegroundDimmed] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIconSelected] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsUrl] = {gfx::kGoogleBlue700}; +- mixer[kColorSearchboxResultsUrlSelected] = {gfx::kGoogleBlue700}; +- mixer[kColorSearchboxSearchIconBackground] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIcon] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIconFocusedOutline] = {gfx::kGoogleBlue600}; ++ mixer[kColorSearchboxResultsDimSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsFocusIndicator] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue600}; ++ mixer[kColorSearchboxResultsForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(SK_ColorBLACK)}; ++ mixer[kColorSearchboxResultsForegroundDimmed] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconContainerBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxResultsUrl] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue700}; ++ mixer[kColorSearchboxResultsUrlSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue700}; ++ mixer[kColorSearchboxSearchIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIcon] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconFocusedOutline] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue600}; + mixer[kColorSearchboxShadow] = + ui::SetAlpha(gfx::kGoogleGrey900, + (dark_mode ? /* % opacity */ 0.32 : 0.28) * SK_AlphaOPAQUE); +diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc +index 4e5901f95885b..8617e0e7afe91 100644 +--- a/chrome/browser/ui/layout_constants.cc ++++ b/chrome/browser/ui/layout_constants.cc +@@ -29,7 +29,7 @@ int GetLayoutConstant(LayoutConstant constant) { + case BOOKMARK_BAR_HEIGHT: { + // The fixed margin ensures the bookmark buttons appear centered relative + // to the white space above and below. +- const int bookmark_bar_attached_vertical_margin = 6; ++ const int bookmark_bar_attached_vertical_margin = 10; + return GetLayoutConstant(BOOKMARK_BAR_BUTTON_HEIGHT) + + bookmark_bar_attached_vertical_margin; + } +@@ -93,12 +93,12 @@ int GetLayoutConstant(LayoutConstant constant) { + case TAB_CLOSE_BUTTON_SIZE: + return touch_ui ? 24 : 16; + case TAB_HEIGHT: +- return 34 + GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP); ++ return 36 + GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP); + case TAB_STRIP_HEIGHT: + return GetLayoutConstant(TAB_HEIGHT) + + GetLayoutConstant(TAB_STRIP_PADDING); + case TAB_STRIP_PADDING: +- return 6; ++ return 4; + case TAB_SEPARATOR_HEIGHT: + return touch_ui ? 24 : 20; + case TAB_PRE_TITLE_PADDING: +diff --git a/chrome/browser/ui/tabs/tab_style.cc b/chrome/browser/ui/tabs/tab_style.cc +index eb6789e6212b6..a3894efb96e6a 100644 +--- a/chrome/browser/ui/tabs/tab_style.cc ++++ b/chrome/browser/ui/tabs/tab_style.cc +@@ -27,8 +27,8 @@ constexpr int kChromeRefreshSeparatorHeight = 16; + constexpr int kChromeRefreshTabVerticalPadding = 6; + constexpr int kChromeRefreshTabHorizontalPadding = 8; + +-// The standard tab width is 232 DIP, excluding separators and overlap. +-constexpr int kTabWidth = 232; ++// The standard tab width is 200 DIP, excluding separators and overlap. ++constexpr int kTabWidth = 200; + + } // namespace + +diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc +index 2934bdcab48bb..9aa1eaf769176 100644 +--- a/chrome/browser/ui/toolbar/app_menu_model.cc ++++ b/chrome/browser/ui/toolbar/app_menu_model.cc +@@ -2241,7 +2241,7 @@ bool AppMenuModel::AddDefaultBrowserMenuItems() { + IDC_SET_BROWSER_AS_DEFAULT, + l10n_util::GetStringUTF16(IDS_SET_BROWSER_AS_DEFAULT_MENU_ITEM), + ui::ImageModel::FromVectorIcon(omnibox::kProductChromeRefreshIcon, +- ui::kColorMenuIcon, kDefaultIconSize)); ++ ui::kColorMenuIconOnEmphasizedBackground, kDefaultIconSize)); + SetElementIdentifierAt(GetItemCount() - 1, + AppMenuModel::kSetBrowserAsDefaultMenuItem); + return true; +diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +index a00e5c202067f..ba59857e8378a 100644 +--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc ++++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +@@ -708,26 +708,7 @@ void BookmarkBarView::Layout(PassKey) { + + const int button_height = GetLayoutConstant(BOOKMARK_BAR_BUTTON_HEIGHT); + +- // Bookmark bar buttons should be centered between the bottom of the location +- // bar and the bottom of the bookmarks bar, which requires factoring in the +- // bottom margin of the toolbar into the button position. +- int toolbar_bottom_margin = 0; +- // Note: |browser_view_| may be null during tests. +- if (browser_view_ && !browser_view_->IsFullscreen()) { +- toolbar_bottom_margin = +- browser_view_->toolbar()->height() - +- browser_view_->GetLocationBarView()->bounds().bottom(); +- } +- // Center the buttons in the total available space. +- const int total_height = GetContentsBounds().height() + toolbar_bottom_margin; +- const auto center_y = [total_height, toolbar_bottom_margin](int height) { +- const int top_margin = (total_height - height) / 2; +- // Calculate the top inset in the bookmarks bar itself (not counting the +- // space in the toolbar) but do not allow the buttons to leave the bookmarks +- // bar. +- return std::max(0, top_margin - toolbar_bottom_margin); +- }; +- const int y = center_y(button_height); ++ const int y = 5; + + gfx::Size all_bookmarks_pref = all_bookmarks_button_->GetVisible() + ? all_bookmarks_button_->GetPreferredSize() +@@ -835,7 +816,7 @@ void BookmarkBarView::Layout(PassKey) { + gfx::Size saved_tab_groups_separator_view_pref = + saved_tab_groups_separator_view_->GetPreferredSize(); + saved_tab_groups_separator_view_->SetBounds( +- x, center_y(saved_tab_groups_separator_view_pref.height()), ++ x, 5 + (button_height - saved_tab_groups_separator_view_pref.height()) / 2, + saved_tab_groups_separator_view_pref.width(), + saved_tab_groups_separator_view_pref.height()); + +@@ -905,7 +886,7 @@ void BookmarkBarView::Layout(PassKey) { + // Bookmarks Separator. + if (bookmarks_separator_view_->GetVisible()) { + bookmarks_separator_view_->SetBounds( +- x, center_y(bookmarks_separator_pref.height()), ++ x, 5 + (button_height - bookmarks_separator_pref.height()) / 2, + bookmarks_separator_pref.width(), bookmarks_separator_pref.height()); + + x += bookmarks_separator_pref.width(); +@@ -1107,6 +1088,11 @@ views::View::DropCallback BookmarkBarView::GetDropCallback( + + void BookmarkBarView::OnThemeChanged() { + views::AccessiblePaneView::OnThemeChanged(); ++ if (GetColorProvider()) { ++ SetBorder(views::CreateSolidSidedBorder( ++ gfx::Insets::TLBR(1, 0, 0, 0), ++ GetColorProvider()->GetColor(kColorToolbarSeparator))); ++ } + UpdateAppearanceForTheme(); + } + +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc +index da82293cba539..2dbe7d318cd7b 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc +@@ -20,7 +20,6 @@ + #include "build/build_config.h" + #include "chrome/app/chrome_command_ids.h" + #include "chrome/app/vector_icons/vector_icons.h" +-#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h" + #include "chrome/browser/browser_process.h" + #include "chrome/browser/command_updater.h" + #include "chrome/browser/content_settings/host_content_settings_map_factory.h" +@@ -41,6 +40,7 @@ + #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h" + #include "chrome/browser/ui/browser.h" + #include "chrome/browser/ui/browser_actions.h" ++#include "chrome/browser/ui/browser_commands.h" + #include "chrome/browser/ui/browser_element_identifiers.h" + #include "chrome/browser/ui/browser_finder.h" + #include "chrome/browser/ui/browser_window.h" +@@ -465,21 +465,7 @@ void LocationBarView::Init() { + // |browser_| may be null when LocationBarView is used for non-Browser windows + // such as PresentationReceiverWindowView, which do not support page actions. + if (browser_) { +- // Page action icons that participate in label animations should be added +- // first so that they appear on the left side of the icon container. +- // TODO(crbug.com/40835681): Improve the ordering heuristics for page action +- // icons and determine a way to handle simultaneous icon animations. +- if (base::FeatureList::IsEnabled(commerce::kProductSpecifications)) { +- params.types_enabled.push_back( +- PageActionIconType::kProductSpecifications); +- } +- params.types_enabled.push_back(PageActionIconType::kDiscounts); +- params.types_enabled.push_back(PageActionIconType::kPriceInsights); +- params.types_enabled.push_back(PageActionIconType::kPriceTracking); +- +- if (optimization_guide::features::ShouldEnableOptimizationGuideIconView()) { +- params.types_enabled.push_back(PageActionIconType::kOptimizationGuide); +- } ++ // Keep only essential page action icons, removing Google-specific features + params.types_enabled.push_back(PageActionIconType::kClickToCall); + params.types_enabled.push_back(PageActionIconType::kAutofillAddress); + params.types_enabled.push_back(PageActionIconType::kManagePasswords); +@@ -491,7 +477,6 @@ void LocationBarView::Init() { + params.types_enabled.push_back(PageActionIconType::kTranslate); + params.types_enabled.push_back(PageActionIconType::kZoom); + params.types_enabled.push_back(PageActionIconType::kFileSystemAccess); +- + params.types_enabled.push_back(PageActionIconType::kCookieControls); + params.types_enabled.push_back( + PageActionIconType::kPaymentsOfferNotification); +@@ -503,54 +488,6 @@ void LocationBarView::Init() { + params.types_enabled.push_back(PageActionIconType::kVirtualCardEnroll); + params.types_enabled.push_back(PageActionIconType::kMandatoryReauth); + +- if (browser_ && lens::features::IsOmniboxEntryPointEnabled()) { +- // The persistent compact entrypoint should be positioned directly before +- // the star icon and the prominent expanding entrypoint should be +- // positioned in the leading position. This entrypoint will be suppressed +- // if the AIM page action is enabled and the user meets AIM eligibility +- // criteria, since we want to avoid both showing up when the user focuses +- // the Omnibox. +- if (lens::features::IsOmniboxEntrypointAlwaysVisible()) { +- params.types_enabled.push_back(PageActionIconType::kLensOverlay); +- } else { +- params.types_enabled.insert(params.types_enabled.begin(), +- PageActionIconType::kLensOverlay); +- } +- } +- +- if (browser_ && lens::features::IsLensOverlayEduActionChipEnabled()) { +- // Position in the leading position, like the expanding entrypoint for +- // kLensOverlay above. While both chips may be enabled, they will not appear +- // at the same time due to different focus behavior. +- params.types_enabled.insert(params.types_enabled.begin(), +- PageActionIconType::kLensOverlayHomework); +- } +- +- // Because the AIM eligibility service might not be ready on startup, +- // the AI Mode page action type is always added. Unless the main AIM +- // omnibox entrypoint Feature is explicitly disabled, which can be used +- // as a kill switch in case of any unanticipated issues with this +- // approach. +- auto* feature_list = base::FeatureList::GetInstance(); +- bool aim_omnibox_entrypoint_explicitly_disabled = +- feature_list && +- feature_list->IsFeatureOverridden( +- omnibox::kAiModeOmniboxEntryPoint.name) && +- !base::FeatureList::IsEnabled(omnibox::kAiModeOmniboxEntryPoint); +- if (!aim_omnibox_entrypoint_explicitly_disabled) { +- // Position in the leading position, like the entrypoint for +- // kLensOverlayHomework above. While both chips may be enabled, they will +- // not appear at the same time due to different focus behavior. The +- // visibility of this entrypoint is dependent on whether or not the user +- // meets AIM eligibility criteria. +- params.types_enabled.insert(params.types_enabled.begin(), +- PageActionIconType::kAiMode); +- } +- +- if (browser_ && tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) { +- params.types_enabled.push_back(PageActionIconType::kCollaborationMessaging); +- } +- + if (browser_ && !is_popup_mode_) { + params.types_enabled.push_back(PageActionIconType::kBookmarkStar); + } +@@ -566,17 +503,6 @@ void LocationBarView::Init() { + AddChildView(std::make_unique(params)); + page_action_icon_controller_ = page_action_icon_container_->controller(); + +- if (!page_action_icon_container_->children().empty() && +- !aim_omnibox_entrypoint_explicitly_disabled && +- !IsPageActionMigrated(PageActionIconType::kAiMode)) { +- auto* first_page_action_icon_view = static_cast( +- page_action_icon_container_->children().front()); +- DCHECK(first_page_action_icon_view->action_id() == kActionAiMode) +- << "kActionAiMode must be the first child in " +- "PageActionIconContainerView to ensure it's the left-most page " +- "action."; +- } +- + auto clear_all_button = views::CreateVectorImageButton(base::BindRepeating( + static_cast( + &OmniboxView::SetUserText), +@@ -586,6 +512,22 @@ void LocationBarView::Init() { + clear_all_button_ = AddChildView(std::move(clear_all_button)); + RefreshClearAllButtonIcon(); + ++ // Add copy URL button ++ auto copy_url_button = views::CreateVectorImageButton(base::BindRepeating( ++ [](Browser* browser) { ++ if (browser) { ++ chrome::ExecuteCommand(browser, IDC_COPY_URL); ++ } ++ }, ++ base::Unretained(browser_))); ++ copy_url_button->SetTooltipText( ++ l10n_util::GetStringUTF16(IDS_COPY_URL)); ++ copy_url_button->SetImageModel( ++ views::Button::STATE_NORMAL, ++ ui::ImageModel::FromVectorIcon(kLinkChromeRefreshIcon, kColorOmniboxResultsIcon, ++ GetLayoutConstant(LOCATION_BAR_ICON_SIZE))); ++ copy_url_button_ = AddChildView(std::move(copy_url_button)); ++ + // Initialize the location entry. We do this to avoid a black flash which is + // visible when the location entry has just been initialized. + Update(nullptr); +@@ -963,25 +905,9 @@ void LocationBarView::Layout(PassKey) { + } + }; + +- // When the AIM page action is shown as the right-most page action in the +- // location bar, it should be positioned flush against the right edge of the +- // location bar. +- // If all page actions are migrated (i.e. up to bookmark star), then the extra +- // padding that is usually added to bridge the new and legacy containers can +- // be discounted. +- const bool all_page_actions_migrated = +- IsPageActionMigrated(PageActionIconType::kBookmarkStar); +- const int kTrailingEdgePaddingForAim = +- IsPageActionMigrated(PageActionIconType::kAiMode) && +- !all_page_actions_migrated +- ? -3 +- : 5; + add_trailing_decoration(page_action_icon_container_, + /*intra_item_padding=*/0, +- /*edge_padding=*/ +- IsAimLastVisiblePageAction() +- ? kTrailingEdgePaddingForAim +- : trailing_decorations_edge_padding); ++ /*edge_padding=*/trailing_decorations_edge_padding); + add_trailing_decoration(page_action_container_, + /*intra_item_padding=*/0, + /*edge_padding=*/trailing_decorations_edge_padding); +@@ -1000,6 +926,9 @@ void LocationBarView::Layout(PassKey) { + add_trailing_decoration(clear_all_button_, /*intra_item_padding=*/0, + /*edge_padding=*/trailing_decorations_edge_padding); + ++ add_trailing_decoration(copy_url_button_, /*intra_item_padding=*/0, ++ /*edge_padding=*/trailing_decorations_edge_padding); ++ + // Perform layout. + int entry_width = width(); + +@@ -1272,6 +1201,11 @@ bool LocationBarView::ShouldHidePageActionIcons() const { + + bool LocationBarView::ShouldHidePageActionIcon( + PageActionIconView* icon_view) const { ++ // Bookmark star should always be visible ++ if (page_action_icon_controller_->GetIconType(icon_view) == PageActionIconType::kBookmarkStar) { ++ return false; ++ } ++ + if (ShouldHidePageActionIcons()) { + return true; + } +@@ -1294,25 +1228,8 @@ bool LocationBarView::ShouldHidePageActionIcon( + + bool LocationBarView::ShouldHidePageActionIconsForContext( + metrics::OmniboxEventProto::PageClassification page_context) const { +- switch (page_context) { +- case metrics::OmniboxEventProto:: +- INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS: { +- // When the user is on the NTP and the AIM page action is eligible to be +- // shown, suppress all other page actions in order to minimize UI +- // instability when going from the steady-state to the on-focus Omnibox. +- const auto* aim_eligibility_service = +- AimEligibilityServiceFactory::GetForProfile(profile_); +- const bool is_aim_page_action_enabled = +- OmniboxFieldTrial::IsAimOmniboxEntrypointEnabled( +- aim_eligibility_service); +- const bool hide_other_page_actions_on_ntp = +- omnibox_feature_configs::AiModeOmniboxEntryPoint::Get() +- .hide_other_page_actions_on_ntp; +- return is_aim_page_action_enabled && hide_other_page_actions_on_ntp; +- } +- default: +- return false; +- } ++ // AI Mode removed - no special hiding logic needed ++ return false; + } + + /* +@@ -1361,42 +1278,7 @@ bool LocationBarView::ShouldHidePageActionIconsForContext( + * of how many migrated page actions are visible). + */ + bool LocationBarView::IsAimLastVisiblePageAction() const { +- int visible_migrated_page_action_count = 0; +- bool migrated_aim_page_action_is_visible = false; +- +- // Check PageActionContainerView (migrated page actions). +- for (views::View* view : page_action_container_->children()) { +- if (view->GetVisible()) { +- visible_migrated_page_action_count++; +- page_actions::PageActionView* page_action_view = +- static_cast(view); +- if (page_action_view->GetActionId() == kActionAiMode) { +- migrated_aim_page_action_is_visible = true; +- } +- } +- } +- +- int visible_page_action_count = 0; +- bool aim_page_action_is_visible = false; +- +- // Check PageActionIconContainerView (legacy page actions). +- for (views::View* view : page_action_icon_container_->children()) { +- if (view->GetVisible()) { +- visible_page_action_count++; +- PageActionIconView* icon_view = static_cast(view); +- if (icon_view->action_id() == kActionAiMode) { +- aim_page_action_is_visible = true; +- } +- } +- } +- +- if (migrated_aim_page_action_is_visible && +- (visible_migrated_page_action_count + visible_page_action_count) == 1) { +- return true; +- } else if (aim_page_action_is_visible && visible_page_action_count == 1) { +- return true; +- } +- ++ // AI Mode removed - always return false + return false; + } + +@@ -1466,9 +1348,9 @@ void LocationBarView::RefreshBackground() { + ui::NativeTheme::PreferredContrast::kMore; + + const auto* const color_provider = GetColorProvider(); +- SkColor normal = color_provider->GetColor(kColorLocationBarBackground); ++ SkColor normal = color_provider->GetColor(kColorToolbar); + SkColor hovered = +- color_provider->GetColor(kColorLocationBarBackgroundHovered); ++ color_provider->GetColor(kColorToolbar); + + background_color_ = gfx::Tween::ColorValueBetween(opacity, normal, hovered); + if (is_caret_visible) { +@@ -1565,20 +1447,7 @@ void LocationBarView::RefreshPageActionIconViews() { + } + + void LocationBarView::RefreshAiModePageActionIconView() { +- if (IsPageActionMigrated(PageActionIconType::kAiMode)) { +- auto* aim_page_action_controller = +- omnibox::AiModePageActionController::From(browser_); +- if (aim_page_action_controller) { +- aim_page_action_controller->UpdatePageAction(); +- } +- return; +- } +- +- PageActionIconView* aim_icon_view = +- page_action_icon_controller_->GetIconView(PageActionIconType::kAiMode); +- if (aim_icon_view) { +- aim_icon_view->Update(); +- } ++ // AI Mode removed - no-op + } + + void LocationBarView::RefreshPageActionContainerViewAndIconsVisibility( +@@ -1912,13 +1781,12 @@ void LocationBarView::OnChanged() { + !omnibox_view_->GetText().empty() && + IsVirtualKeyboardVisible(GetWidget())); + ++ // Copy URL button is always visible ++ copy_url_button_->SetVisible(true); ++ + InvalidateLayout(); + SchedulePaint(); + UpdateChipVisibility(); +- // The AI mode page action icon view visibility depends on whether or not +- // user text has been entered into the omnibox, so refresh the icon on +- // changes. +- RefreshAiModePageActionIconView(); + } + + const LocationBarModel* LocationBarView::GetLocationBarModel() const { +@@ -1934,10 +1802,6 @@ void LocationBarView::OnOmniboxFocused() { + // the omnibox is intentional, snapping is better than transitioning here. + hover_animation_.Reset(); + RefreshBackground(); +- +- // The AI mode page action icon view should only be visible when the omnibox +- // is focused, so if there is a change in focus, refresh the icon. +- RefreshAiModePageActionIconView(); + } + + void LocationBarView::OnOmniboxBlurred() { +@@ -1946,10 +1810,6 @@ void LocationBarView::OnOmniboxBlurred() { + } + RefreshBackground(); + +- // The AI mode page action icon view should only be visible when the omnibox +- // is focused, so if there is a change in focus, refresh the icon. +- RefreshAiModePageActionIconView(); +- + location_icon_view_->Update(false, false); + } + +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h +index 507ca6272a7b1..7993f100b5281 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.h ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.h +@@ -570,6 +570,9 @@ class LocationBarView + // user to clear all text. + raw_ptr clear_all_button_ = nullptr; + ++ // A button to copy the current URL to clipboard. ++ raw_ptr copy_url_button_ = nullptr; ++ + // Animation to change whole location bar background color on hover. + gfx::SlideAnimation hover_animation_{this}; + +diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc +index 93a656042af50..d5306a85b1e0c 100644 +--- a/chrome/browser/ui/views/tabs/tab.cc ++++ b/chrome/browser/ui/views/tabs/tab.cc +@@ -1167,10 +1167,10 @@ void Tab::UpdateIconVisibility() { + #if BUILDFLAG(IS_CHROMEOS) + // Hide tab close button for OnTask if locked. Only applicable for non-web + // browser scenarios. +- showing_close_button_ = !controller_->IsLockedForOnTask(); ++ showing_close_button_ = !controller_->IsLockedForOnTask() && mouse_hovered_; + #else +- // Close button is shown on active tabs regardless of the size. +- showing_close_button_ = true; ++ // Close button is shown on active tabs only when hovered. ++ showing_close_button_ = mouse_hovered_; + #endif // BUILDFLAG(IS_CHROMEOS) + available_width -= close_button_width; + +@@ -1196,11 +1196,12 @@ void Tab::UpdateIconVisibility() { + available_width -= favicon_width; + } + ++ // Only show close button on hover for inactive tabs + showing_close_button_ = + #if BUILDFLAG(IS_CHROMEOS) + !controller_->IsLockedForOnTask() && + #endif +- large_enough_for_close_button; ++ large_enough_for_close_button && mouse_hovered_; + if (showing_close_button_) { + available_width -= close_button_width; + } +diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc +index fe66c423ab248..1346e9de8e2e5 100644 +--- a/chrome/browser/ui/views/tabs/tab_style_views.cc ++++ b/chrome/browser/ui/views/tabs/tab_style_views.cc +@@ -210,8 +210,6 @@ SkPath TabStyleViewsImpl::GetPath(TabStyle::PathType path_type, + CHECK(tab()); + const int stroke_thickness = GetStrokeThickness(flags.force_active); + +- const TabStyle::TabSelectionState state = GetSelectionState(); +- + // We'll do the entire path calculation in aligned pixels. + // TODO(dfried): determine if we actually want to use `stroke_thickness` as + // the inset in this case. +@@ -229,8 +227,8 @@ SkPath TabStyleViewsImpl::GetPath(TabStyle::PathType path_type, + scale; + + // Selected, hover, and inactive tab fills are a detached squarcle tab. +- if ((path_type == TabStyle::PathType::kFill && +- state != TabStyle::TabSelectionState::kActive) || ++ // Active tabs also use this shape for consistent rounded rectangle appearance. ++ if ((path_type == TabStyle::PathType::kFill) || + path_type == TabStyle::PathType::kHighlight || + path_type == TabStyle::PathType::kInteriorClip || + path_type == TabStyle::PathType::kHitTest) { +@@ -1031,8 +1029,8 @@ void TabStyleViewsImpl::PaintBackgroundStroke( + } + + SkPath outer_path = +- GetPath(TabStyle::PathType::kBorder, canvas->image_scale(), +- {.force_active = is_active, .should_paint_extension = false}); ++ GetPath(TabStyle::PathType::kFill, canvas->image_scale(), ++ {.force_active = is_active}); + gfx::ScopedCanvas scoped_canvas(canvas); + float scale = canvas->UndoDeviceScaleFactor(); + cc::PaintFlags flags; +@@ -1063,12 +1061,19 @@ void TabStyleViewsImpl::PaintSeparators(gfx::Canvas* canvas) const { + + cc::PaintFlags flags; + flags.setAntiAlias(true); ++ flags.setStyle(cc::PaintFlags::kStroke_Style); ++ flags.setStrokeWidth(1.0f * scale); ++ ++ // Draw simple vertical lines instead of rounded rectangles + flags.setColor(separator_color(separator_opacities.left)); +- canvas->DrawRoundRect(separator_bounds.leading, +- tab_style()->GetSeparatorCornerRadius() * scale, flags); ++ float left_x = separator_bounds.leading.x() + separator_bounds.leading.width() / 2; ++ canvas->DrawLine(gfx::PointF(left_x, separator_bounds.leading.y()), ++ gfx::PointF(left_x, separator_bounds.leading.bottom()), flags); ++ + flags.setColor(separator_color(separator_opacities.right)); +- canvas->DrawRoundRect(separator_bounds.trailing, +- tab_style()->GetSeparatorCornerRadius() * scale, flags); ++ float right_x = separator_bounds.trailing.x() + separator_bounds.trailing.width() / 2; ++ canvas->DrawLine(gfx::PointF(right_x, separator_bounds.trailing.y()), ++ gfx::PointF(right_x, separator_bounds.trailing.bottom()), flags); + } + + bool TabStyleViewsImpl::IsLeftSplitTab(const Tab* tab) const { +diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc +index d10401dad12b2..da0cca83c497f 100644 +--- a/chrome/browser/ui/views/toolbar/app_menu.cc ++++ b/chrome/browser/ui/views/toolbar/app_menu.cc +@@ -1597,6 +1597,7 @@ void AppMenu::PopulateMenu(MenuItemView* parent, MenuModel* model) { + views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_CONTROL_VERTICAL_TEXT_PADDING), + ui::kColorAppMenuUpgradeRowBackground); ++ item->SetForegroundColorId(ui::kColorAppMenuUpgradeRowSubstringForeground); + } + break; + } +diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc +index 0a324e3999d7a..e86eec19bd872 100644 +--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc ++++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc +@@ -413,6 +413,16 @@ void ToolbarView::Init() { + + location_bar_ = container_view_->AddChildView(std::move(location_bar)); + ++ // Add a divider after the location bar ++ auto location_bar_divider = std::make_unique(); ++ location_bar_divider_ = container_view_->AddChildView(std::move(location_bar_divider)); ++ location_bar_divider_->SetPreferredSize( ++ gfx::Size(GetLayoutConstant(TOOLBAR_DIVIDER_WIDTH), ++ GetLayoutConstant(TOOLBAR_DIVIDER_HEIGHT))); ++ location_bar_divider_->SetBackground(views::CreateRoundedRectBackground( ++ kColorToolbarSeparator, ++ GetLayoutConstant(TOOLBAR_DIVIDER_CORNER_RADIUS))); ++ + if (extensions_container) { + extensions_container_ = + container_view_->AddChildView(std::move(extensions_container)); +@@ -1008,6 +1018,12 @@ void ToolbarView::InitLayout() { + gfx::Insets::VH(0, GetLayoutConstant(TOOLBAR_DIVIDER_SPACING))); + } + ++ if (location_bar_divider_) { ++ location_bar_divider_->SetProperty( ++ views::kMarginsKey, ++ gfx::Insets::VH(0, GetLayoutConstant(TOOLBAR_DIVIDER_SPACING))); ++ } ++ + constexpr int kToolbarFlexOrderStart = 1; + + // TODO(crbug.com/40929989): Ignore containers till issue addressed. +diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h +index 415970aadb0ed..d29a28f80fb0c 100644 +--- a/chrome/browser/ui/views/toolbar/toolbar_view.h ++++ b/chrome/browser/ui/views/toolbar/toolbar_view.h +@@ -295,6 +295,7 @@ class ToolbarView : public views::AccessiblePaneView, + raw_ptr split_tabs_ = nullptr; + raw_ptr custom_tab_bar_ = nullptr; + raw_ptr location_bar_ = nullptr; ++ raw_ptr location_bar_divider_ = nullptr; + raw_ptr extensions_container_ = nullptr; + raw_ptr toolbar_divider_ = nullptr; + raw_ptr battery_saver_button_ = nullptr; +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +index 202099eee781e..832ca90c1538c 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +@@ -583,7 +583,7 @@ void NewTabPageHandler::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterIntegerPref( + prefs::kNtpCustomizeChromeSidePanelAutoOpeningsCount, 0); + registry->RegisterBooleanPref(prefs::kNtpCustomizeChromeExplicitlyClosed, +- false); ++ true); + registry->RegisterBooleanPref(prefs::kNtpCustomizeChromeIPHAutoOpened, false); + } + +diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc +index 406d9402d41e1..6d2ea1d68430b 100644 +--- a/components/search/ntp_features.cc ++++ b/components/search/ntp_features.cc +@@ -98,7 +98,7 @@ BASE_FEATURE(kNtpDummyModules, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, Google Drive module will be shown. + // This is a kill switch. Keep indefinitely. +-BASE_FEATURE(kNtpDriveModule, base::FEATURE_ENABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpDriveModule, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, the NTP Drive module does not require sync. + BASE_FEATURE(kNtpDriveModuleHistorySyncRequirement, +@@ -121,7 +121,7 @@ BASE_FEATURE(kNtpMiddleSlotPromo, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, middle slot promo will be dismissed from New Tab Page until new + // promo message is populated +-BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_ENABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_DISABLED_BY_DEFAULT); + + // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". + // This is used for an emergency Finch param. Keep indefinitely. +diff --git a/ui/color/core_default_color_mixer.cc b/ui/color/core_default_color_mixer.cc +index 54cb33c7e3f91..41446d2a935c5 100644 +--- a/ui/color/core_default_color_mixer.cc ++++ b/ui/color/core_default_color_mixer.cc +@@ -25,7 +25,7 @@ void AddCoreDefaultColorMixer(ColorProvider* provider, + DVLOG(2) << "Adding CoreDefaultColorMixer to ColorProvider for " + << (dark_mode ? "Dark" : "Light") << " window."; + ColorMixer& mixer = provider->AddMixer(); +- mixer[kColorAccent] = {dark_mode ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600}; ++ mixer[kColorAccent] = {dark_mode ? SK_ColorWHITE : SK_ColorWHITE}; + // 4.5 and 7.0 approximate the default light and dark theme contrasts of + // accent-against-primary-background. + mixer[kColorAccentWithGuaranteedContrastAtopPrimaryBackground] = +diff --git a/ui/color/mac/native_color_mixers_mac.mm b/ui/color/mac/native_color_mixers_mac.mm +index fb2d49fe27f3d..c740e3b5fa995 100644 +--- a/ui/color/mac/native_color_mixers_mac.mm ++++ b/ui/color/mac/native_color_mixers_mac.mm +@@ -99,11 +99,11 @@ void AddNativeUiColorMixer(ColorProvider* provider, + + mixer[kColorTableBackgroundAlternate] = {skia::NSSystemColorToSkColor( + NSColor.alternatingContentBackgroundColors[1])}; +- if (!key.user_color.has_value()) { +- mixer[kColorSysStateFocusRing] = PickGoogleColor( +- skia::NSSystemColorToSkColor(NSColor.keyboardFocusIndicatorColor), +- kColorSysBase, color_utils::kMinimumVisibleContrastRatio); + ++ // Override focus ring color: white in dark mode, black in light mode ++ mixer[kColorSysStateFocusRing] = {properties.dark ? SK_ColorWHITE : SK_ColorBLACK}; ++ ++ if (!key.user_color.has_value()) { + const SkColor system_highlight_color = + skia::NSSystemColorToSkColor(NSColor.selectedTextBackgroundColor); + mixer[kColorTextSelectionBackground] = {system_highlight_color}; +diff --git a/ui/color/ref_color_mixer.cc b/ui/color/ref_color_mixer.cc +index 3eb2f1053b895..a57a92344f27a 100644 +--- a/ui/color/ref_color_mixer.cc ++++ b/ui/color/ref_color_mixer.cc +@@ -25,36 +25,36 @@ namespace ui { + void AddBaselinePalette(ColorProvider* provider) { + ColorMixer& mixer = provider->AddMixer(); + mixer[kColorRefPrimary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +- mixer[kColorRefPrimary10] = {SkColorSetRGB(0x04, 0x1E, 0x49)}; +- mixer[kColorRefPrimary20] = {SkColorSetRGB(0x06, 0x2E, 0x6F)}; +- mixer[kColorRefPrimary25] = {SkColorSetRGB(0x07, 0x38, 0x88)}; +- mixer[kColorRefPrimary30] = {SkColorSetRGB(0x08, 0x42, 0xA0)}; +- mixer[kColorRefPrimary40] = {SkColorSetRGB(0x0B, 0x57, 0xD0)}; +- mixer[kColorRefPrimary50] = {SkColorSetRGB(0x1B, 0x6E, 0xF3)}; +- mixer[kColorRefPrimary60] = {SkColorSetRGB(0x4C, 0x8D, 0xF6)}; +- mixer[kColorRefPrimary70] = {SkColorSetRGB(0x7C, 0xAC, 0xF8)}; +- mixer[kColorRefPrimary80] = {SkColorSetRGB(0xA8, 0xC7, 0xFA)}; +- mixer[kColorRefPrimary90] = {SkColorSetRGB(0xD3, 0xE3, 0xFD)}; +- mixer[kColorRefPrimary95] = {SkColorSetRGB(0xEC, 0xF3, 0xFE)}; +- mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFB, 0xFF)}; ++ mixer[kColorRefPrimary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; ++ mixer[kColorRefPrimary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; ++ mixer[kColorRefPrimary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; ++ mixer[kColorRefPrimary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; ++ mixer[kColorRefPrimary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; ++ mixer[kColorRefPrimary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; ++ mixer[kColorRefPrimary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; ++ mixer[kColorRefPrimary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; ++ mixer[kColorRefPrimary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; ++ mixer[kColorRefPrimary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; ++ mixer[kColorRefPrimary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; ++ mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; + mixer[kColorRefPrimary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; + + mixer[kColorRefSecondary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +- mixer[kColorRefSecondary10] = {SkColorSetRGB(0x00, 0x1D, 0x35)}; +- mixer[kColorRefSecondary12] = {SkColorSetRGB(0x00, 0x22, 0x38)}; +- mixer[kColorRefSecondary15] = {SkColorSetRGB(0x00, 0x28, 0x45)}; +- mixer[kColorRefSecondary20] = {SkColorSetRGB(0x00, 0x33, 0x55)}; +- mixer[kColorRefSecondary25] = {SkColorSetRGB(0x00, 0x3f, 0x66)}; +- mixer[kColorRefSecondary30] = {SkColorSetRGB(0x00, 0x4A, 0x77)}; +- mixer[kColorRefSecondary35] = {SkColorSetRGB(0x00, 0x57, 0x89)}; +- mixer[kColorRefSecondary40] = {SkColorSetRGB(0x00, 0x63, 0x9B)}; +- mixer[kColorRefSecondary50] = {SkColorSetRGB(0x04, 0x7D, 0xB7)}; +- mixer[kColorRefSecondary60] = {SkColorSetRGB(0x39, 0x98, 0xD3)}; +- mixer[kColorRefSecondary70] = {SkColorSetRGB(0x5A, 0xB3, 0xF0)}; +- mixer[kColorRefSecondary80] = {SkColorSetRGB(0x7F, 0xCF, 0xFF)}; +- mixer[kColorRefSecondary90] = {SkColorSetRGB(0xC2, 0xE7, 0xFF)}; +- mixer[kColorRefSecondary95] = {SkColorSetRGB(0xDF, 0xF3, 0xFF)}; +- mixer[kColorRefSecondary99] = {SkColorSetRGB(0xF7, 0xFC, 0xFF)}; ++ mixer[kColorRefSecondary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; ++ mixer[kColorRefSecondary12] = {SkColorSetRGB(0x1F, 0x1F, 0x1F)}; ++ mixer[kColorRefSecondary15] = {SkColorSetRGB(0x26, 0x26, 0x26)}; ++ mixer[kColorRefSecondary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; ++ mixer[kColorRefSecondary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; ++ mixer[kColorRefSecondary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; ++ mixer[kColorRefSecondary35] = {SkColorSetRGB(0x59, 0x59, 0x59)}; ++ mixer[kColorRefSecondary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; ++ mixer[kColorRefSecondary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; ++ mixer[kColorRefSecondary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; ++ mixer[kColorRefSecondary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; ++ mixer[kColorRefSecondary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; ++ mixer[kColorRefSecondary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; ++ mixer[kColorRefSecondary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; ++ mixer[kColorRefSecondary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; + mixer[kColorRefSecondary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; + + mixer[kColorRefTertiary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +diff --git a/ui/color/sys_color_mixer.cc b/ui/color/sys_color_mixer.cc +index 4745b7f50a28b..6cef161038ae8 100644 +--- a/ui/color/sys_color_mixer.cc ++++ b/ui/color/sys_color_mixer.cc +@@ -31,6 +31,8 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, + : kColorRefSecondary30}; + mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefPrimary30 + : kColorRefPrimary90}; ++ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; + mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefPrimary10 + : kColorRefPrimary90}; + mixer[kColorSysNeutralContainer] = {dark_mode ? kColorRefNeutralVariant15 +@@ -39,18 +41,18 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, + : kColorRefPrimary90}; + + // Chrome surfaces. +- mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary25 ++ mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary10 + : kColorRefNeutral98}; +- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary15 ++ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary25 + : kColorSysSurface4}; + mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefSecondary25 + : kColorRefNeutral98}; + +- mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary12 ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary10 + : kColorRefSecondary90}; + mixer[kColorSysHeaderContainer] = {dark_mode ? kColorRefSecondary25 + : kColorRefPrimary95}; +- mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral25 ++ mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral99}; + mixer[kColorSysOnHeaderDivider] = {dark_mode ? kColorRefSecondary25 + : kColorRefPrimary80}; +@@ -78,12 +80,12 @@ void AddGrayscaleSysColorOverrides(ColorMixer& mixer, + + // General + mixer[kColorSysOnSurfacePrimary] = {dark_mode ? kColorRefNeutral90 +- : kColorRefNeutral10}; +- mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 +- : kColorRefNeutral90}; ++ : kColorRefNeutral10}; ++mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 ++: kColorRefNeutral90}; + + // Chrome surfaces. +- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral90}; + mixer[kColorSysHeaderInactive] = { + dark_mode ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) +@@ -116,24 +118,24 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + ColorMixer& mixer = provider->AddMixer(); + + // Primary. +- mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary80 +- : kColorRefPrimary40}; +- mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary20 +- : kColorRefPrimary100}; +- mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary30 +- : kColorRefPrimary90}; +- mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary90 +- : kColorRefPrimary10}; ++ mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; ++ mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary10 ++ : kColorRefPrimary90}; ++ mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; ++ mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary10 ++ : kColorRefPrimary90}; + + // Secondary. +- mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary80 +- : kColorRefSecondary40}; +- mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary20 +- : kColorRefSecondary100}; +- mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary30 +- : kColorRefSecondary90}; +- mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary90 +- : kColorRefSecondary10}; ++ mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary90 ++ : kColorRefSecondary10}; ++ mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary10 ++ : kColorRefSecondary90}; ++ mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary90 ++ : kColorRefSecondary10}; ++ mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary10 ++ : kColorRefSecondary90}; + // Tertiary. + mixer[kColorSysTertiary] = {dark_mode ? kColorRefTertiary80 + : kColorRefTertiary40}; +@@ -179,8 +181,8 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + mixer[kColorSysSurface] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral100}; + mixer[kColorSysSurfaceNumberedForeground] = { +- dark_mode ? SkColorSetRGB(0xD1, 0xE1, 0xFF) +- : SkColorSetRGB(0x69, 0x91, 0xD6)}; ++ dark_mode ? kColorRefNeutral90 ++ : kColorRefNeutral10}; + mixer[kColorSysSurface1] = AlphaBlend({kColorSysSurfaceNumberedForeground}, + {kColorSysSurface}, 0x0C); + mixer[kColorSysSurface2] = AlphaBlend({kColorSysSurfaceNumberedForeground}, +@@ -202,10 +204,10 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + mixer[kColorSysOnSurfacePrimaryInactive] = {dark_mode ? kColorRefNeutral90 + : kColorRefNeutral10}; + +- mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary30 +- : kColorRefPrimary90}; +- mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary90 +- : kColorRefPrimary10}; ++ mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary100 ++ : kColorRefPrimary0}; ++ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary0 ++ : kColorRefPrimary100}; + mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefSecondary10 + : kColorRefPrimary90}; + mixer[kColorSysOnBaseTonalContainer] = {dark_mode ? kColorRefSecondary90 +@@ -220,14 +222,13 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + : kColorRefPrimary90}; + + // Chrome surfaces. +- mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral25 : kColorRefNeutral100}; +- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral15 +- : kColorSysSurface4}; ++ mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral10 : kColorRefNeutral100}; ++ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral25 : kColorSysSurface4}; + mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefNeutral25 + : kColorRefNeutral100}; + +- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 +- : kColorRefPrimary90}; ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 ++ : kColorRefNeutral90}; + mixer[kColorSysHeaderInactive] = { + dark_mode + ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) +diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h +index cd70752a23e34..6725f520d89c2 100644 +--- a/ui/views/controls/menu/menu_item_view.h ++++ b/ui/views/controls/menu/menu_item_view.h +@@ -186,6 +186,10 @@ class VIEWS_EXPORT MenuItemView : public View, public LayoutDelegate { + + std::optional GetSelectedColorId() { return selected_color_id_; } + ++ void SetForegroundColorId(std::optional foreground_color_id) { ++ foreground_color_id_ = foreground_color_id; ++ } ++ + void SetHighlightWhenSelectedWithChildViews( + bool highlight_when_selected_with_child_views) { + highlight_when_selected_with_child_views_ = +@@ -596,10 +600,6 @@ class VIEWS_EXPORT MenuItemView : public View, public LayoutDelegate { + // Calculates the X coordinate of the icon. + int CalculateIconX(const ImageView* icon_view) const; + +- void SetForegroundColorId(std::optional foreground_color_id) { +- foreground_color_id_ = foreground_color_id; +- } +- + // Returns the corresponding margin from the `MenuConfig` if + // `vertical_margin_` is not set. + int GetVerticalMargin() const; +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.css b/ui/webui/resources/cr_components/searchbox/searchbox.css +index 34e70f33711a1..dc4fdb93e0fa3 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox.css +@@ -299,7 +299,7 @@ cr-searchbox-icon { + + :host([use-webkit-search-icons_][compose-button-enabled]) #voiceSearchButton, + :host([use-webkit-search-icons_][compose-button-enabled]) #lensSearchButton { +- background-color: #1F1F1F; ++ background-color: var(--color-searchbox-lens-voice-icon-background); + } + + :host([compose-button-enabled][searchbox-lens-search-enabled_]) { +diff --git a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts +index 6c77613866851..8c2a9b66df274 100644 +--- a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts ++++ b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts +@@ -29,26 +29,26 @@ export const DARK_DEFAULT_COLOR: Color = { + }; + + export const LIGHT_BASELINE_BLUE_COLOR: Color = { +- background: {value: 0xff0b57d0}, +- foreground: {value: 0xffd3e3fd}, +- base: {value: 0xffc7c7c7}, ++ background: {value: 0xff000000}, ++ foreground: {value: 0xffffffff}, ++ base: {value: 0xff606060}, + }; + + export const DARK_BASELINE_BLUE_COLOR: Color = { +- background: {value: 0xffa8c7fa}, +- foreground: {value: 0xff0842a0}, ++ background: {value: 0xffffffff}, ++ foreground: {value: 0xff000000}, + base: {value: 0xff757575}, + }; + + export const LIGHT_BASELINE_GREY_COLOR: Color = { +- background: {value: 0xff0b57d0}, +- foreground: {value: 0xffe3e3e3}, +- base: {value: 0xffc7c7c7}, ++ background: {value: 0xff000000}, ++ foreground: {value: 0xffffffff}, ++ base: {value: 0xff606060}, + }; + + export const DARK_BASELINE_GREY_COLOR: Color = { +- background: {value: 0xffa8c7fa}, +- foreground: {value: 0xff474747}, ++ background: {value: 0xffffffff}, ++ foreground: {value: 0xff000000}, + base: {value: 0xff757575}, + }; + diff --git a/chromium/scripts/apply_patches.sh b/chromium/scripts/apply_patches.sh new file mode 100755 index 0000000..dd3d1f9 --- /dev/null +++ b/chromium/scripts/apply_patches.sh @@ -0,0 +1,165 @@ +#!/bin/bash +# OpenBrowser Patch Application Script +# Usage: ./apply_patches.sh + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Check arguments +if [ $# -ne 2 ]; then + echo -e "${RED}Usage: $0 ${NC}" + echo "" + echo "Example:" + echo " $0 ./patches ../chromium/src" + exit 1 +fi + +PATCHES_DIR="$1" +SOURCE_DIR="$2" + +# Convert to absolute paths +PATCHES_DIR="$(cd "$PATCHES_DIR" 2>/dev/null && pwd)" || { + echo -e "${RED}Error: Patches directory not found: $1${NC}" + exit 1 +} + +SOURCE_DIR="$(cd "$SOURCE_DIR" 2>/dev/null && pwd)" || { + echo -e "${RED}Error: Source directory not found: $2${NC}" + exit 1 +} + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}OpenBrowser Patch Application Script${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" +echo -e "Patches Directory: ${GREEN}$PATCHES_DIR${NC}" +echo -e "Source Directory: ${GREEN}$SOURCE_DIR${NC}" +echo "" + +# Find all patch files and sort them +mapfile -t PATCH_FILES < <(find "$PATCHES_DIR" -name "*.patch" -type f | sort) + +if [ ${#PATCH_FILES[@]} -eq 0 ]; then + echo -e "${YELLOW}No patch files found in $PATCHES_DIR${NC}" + exit 0 +fi + +echo -e "${GREEN}Found ${#PATCH_FILES[@]} patch file(s):${NC}" +for i in "${!PATCH_FILES[@]}"; do + RELATIVE_PATH="${PATCH_FILES[$i]#$PATCHES_DIR/}" + echo -e " $((i+1)). $RELATIVE_PATH" +done +echo "" + +# Statistics +APPLIED=0 +SKIPPED=0 +FAILED=0 + +# Apply patches +for i in "${!PATCH_FILES[@]}"; do + PATCH_FILE="${PATCH_FILES[$i]}" + RELATIVE_PATH="${PATCH_FILE#$PATCHES_DIR/}" + + echo -e "${BLUE}========================================${NC}" + echo -e "${BLUE}Patch $((i+1))/${#PATCH_FILES[@]}: $RELATIVE_PATH${NC}" + echo -e "${BLUE}========================================${NC}" + + # Ask user what to do + while true; do + echo -e "${YELLOW}Options:${NC}" + echo -e " [a] Apply this patch" + echo -e " [s] Skip this patch" + echo -e " [v] View patch contents" + echo -e " [q] Quit (abort remaining patches)" + echo "" + read -p "What would you like to do? [a/s/v/q]: " choice + + case "$choice" in + a|A) + echo -e "${GREEN}Applying patch...${NC}" + cd "$SOURCE_DIR" + + if git apply --check "$PATCH_FILE" 2>/dev/null; then + git apply "$PATCH_FILE" + echo -e "${GREEN}✓ Patch applied successfully!${NC}" + APPLIED=$((APPLIED + 1)) + break + else + echo -e "${RED}✗ Patch failed to apply cleanly${NC}" + echo -e "${YELLOW}Attempting to apply with 3-way merge...${NC}" + + if git apply --3way "$PATCH_FILE" 2>/dev/null; then + echo -e "${GREEN}✓ Patch applied with 3-way merge!${NC}" + APPLIED=$((APPLIED + 1)) + break + else + echo -e "${RED}✗ Patch failed to apply even with 3-way merge${NC}" + FAILED=$((FAILED + 1)) + + echo -e "${YELLOW}Would you like to:${NC}" + echo -e " [c] Continue to next patch" + echo -e " [q] Quit" + read -p "Choice [c/q]: " fail_choice + + if [[ "$fail_choice" == "q" || "$fail_choice" == "Q" ]]; then + echo -e "${RED}Aborting...${NC}" + exit 1 + fi + break + fi + fi + ;; + s|S) + echo -e "${YELLOW}⊘ Skipping patch${NC}" + SKIPPED=$((SKIPPED + 1)) + break + ;; + v|V) + echo -e "${BLUE}--- Patch Contents ---${NC}" + cat "$PATCH_FILE" + echo -e "${BLUE}--- End of Patch ---${NC}" + echo "" + ;; + q|Q) + echo -e "${YELLOW}Quitting...${NC}" + echo "" + echo -e "${BLUE}========================================${NC}" + echo -e "${BLUE}Summary${NC}" + echo -e "${BLUE}========================================${NC}" + echo -e "${GREEN}Applied: $APPLIED${NC}" + echo -e "${YELLOW}Skipped: $SKIPPED${NC}" + echo -e "${RED}Failed: $FAILED${NC}" + echo -e "${BLUE}Aborted: $((${#PATCH_FILES[@]} - APPLIED - SKIPPED - FAILED))${NC}" + exit 0 + ;; + *) + echo -e "${RED}Invalid choice. Please enter a, s, v, or q.${NC}" + ;; + esac + done + echo "" +done + +# Final summary +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}All patches processed!${NC}" +echo -e "${BLUE}========================================${NC}" +echo -e "${GREEN}Applied: $APPLIED${NC}" +echo -e "${YELLOW}Skipped: $SKIPPED${NC}" +echo -e "${RED}Failed: $FAILED${NC}" +echo "" + +if [ $FAILED -gt 0 ]; then + echo -e "${YELLOW}⚠ Some patches failed to apply. Please review the output above.${NC}" + exit 1 +else + echo -e "${GREEN}✓ All patches processed successfully!${NC}" + exit 0 +fi diff --git a/scripts/apply_branding_assets.sh b/scripts/apply_branding_assets.sh new file mode 100755 index 0000000..64bdeab --- /dev/null +++ b/scripts/apply_branding_assets.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# OpenBrowser Branding Assets Application Script +# This script copies branding assets (logos, icons) from the branding_assets/ +# directory to the appropriate locations in the Chromium source tree. + +set -e # Exit on error + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OPENBROWSER_ROOT="$(dirname "$SCRIPT_DIR")" +CHROMIUM_SRC="${CHROMIUM_SRC:-$OPENBROWSER_ROOT/../chromium/src}" + +ASSETS_DIR="$OPENBROWSER_ROOT/branding_assets" + +echo "=========================================" +echo "Applying OpenBrowser Branding Assets" +echo "=========================================" +echo "Assets source: $ASSETS_DIR" +echo "Chromium source: $CHROMIUM_SRC" +echo "" + +if [ ! -d "$CHROMIUM_SRC" ]; then + echo "ERROR: Chromium source directory not found at $CHROMIUM_SRC" + echo "Set CHROMIUM_SRC environment variable or run from correct location" + exit 1 +fi + +if [ ! -d "$ASSETS_DIR" ]; then + echo "ERROR: Branding assets directory not found at $ASSETS_DIR" + exit 1 +fi + +# Function to copy asset with verification +copy_asset() { + local src="$ASSETS_DIR/$1" + local dest="$CHROMIUM_SRC/$2" + + if [ ! -f "$src" ]; then + echo "⚠️ WARNING: Source file not found: $src" + return 1 + fi + + local dest_dir="$(dirname "$dest")" + mkdir -p "$dest_dir" + + cp "$src" "$dest" + echo "✅ Copied: $1 → $2" +} + +echo "Copying macOS app icons..." +copy_asset "mac/app.icns" "chrome/app/theme/chromium/mac/app.icns" +copy_asset "mac/app-temp.icns" "chrome/app/theme/chromium/mac/app-temp.icns" +echo "" + +echo "Copying SVG logos..." +copy_asset "svg/product_logo.svg" "chrome/app/theme/chromium/product_logo.svg" +echo "" + +echo "Copying root product logos..." +copy_asset "product_logo_128.png" "chrome/app/theme/chromium/product_logo_128.png" +copy_asset "product_logo_16.png" "chrome/app/theme/chromium/product_logo_16.png" +copy_asset "product_logo_22_mono.png" "chrome/app/theme/chromium/product_logo_22_mono.png" +copy_asset "product_logo_24.png" "chrome/app/theme/chromium/product_logo_24.png" +copy_asset "product_logo_256.png" "chrome/app/theme/chromium/product_logo_256.png" +copy_asset "product_logo_48.png" "chrome/app/theme/chromium/product_logo_48.png" +copy_asset "product_logo_64.png" "chrome/app/theme/chromium/product_logo_64.png" +echo "" + +echo "Copying 100% scale assets..." +copy_asset "100_percent/product_logo_16.png" "chrome/app/theme/default_100_percent/chromium/product_logo_16.png" +copy_asset "100_percent/product_logo_16_white.png" "chrome/app/theme/default_100_percent/chromium/product_logo_16_white.png" +copy_asset "100_percent/product_logo_32.png" "chrome/app/theme/default_100_percent/chromium/product_logo_32.png" +copy_asset "100_percent/product_logo_32_white.png" "chrome/app/theme/default_100_percent/chromium/product_logo_32_white.png" +copy_asset "100_percent/product_logo_name_22.png" "chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png" +copy_asset "100_percent/product_logo_name_22_white.png" "chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png" +copy_asset "100_percent/product_logo_16_root.png" "chrome/app/theme/default_100_percent/product_logo_16.png" +echo "" + +echo "Copying 200% scale assets..." +copy_asset "200_percent/product_logo_16.png" "chrome/app/theme/default_200_percent/chromium/product_logo_16.png" +copy_asset "200_percent/product_logo_16_white.png" "chrome/app/theme/default_200_percent/chromium/product_logo_16_white.png" +copy_asset "200_percent/product_logo_32.png" "chrome/app/theme/default_200_percent/chromium/product_logo_32.png" +copy_asset "200_percent/product_logo_32_white.png" "chrome/app/theme/default_200_percent/chromium/product_logo_32_white.png" +copy_asset "200_percent/product_logo_name_22.png" "chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png" +copy_asset "200_percent/product_logo_name_22_white.png" "chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png" +echo "" + +echo "Copying common assets (favicons)..." +copy_asset "common/favicon_ntp_100.png" "chrome/app/theme/default_100_percent/common/favicon_ntp.png" +copy_asset "common/favicon_ntp_200.png" "chrome/app/theme/default_200_percent/common/favicon_ntp.png" +echo "" + +echo "Copying new tab page icons..." +copy_asset "ntp_icons/black_logo.svg" "chrome/browser/resources/new_tab_page/icons/Black logo.svg" +copy_asset "ntp_icons/openbrowser_logo_black.png" "chrome/browser/resources/new_tab_page/icons/openbrowser_logo_black.png" +copy_asset "ntp_icons/openbrowser_logo_white.png" "chrome/browser/resources/new_tab_page/icons/openbrowser_logo_white.png" +echo "" + +echo "Copying side panel icons..." +copy_asset "side_panel_icons/mini_new_tab_page.svg" "chrome/browser/resources/side_panel/customize_chrome/icons/mini_new_tab_page.svg" +echo "" + +echo "=========================================" +echo "✅ Branding assets applied successfully!" +echo "=========================================" diff --git a/scripts/apply_patches.sh b/scripts/apply_patches.sh new file mode 100755 index 0000000..2817a05 --- /dev/null +++ b/scripts/apply_patches.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# OpenBrowser Patch Application Script +# This script applies all OpenBrowser patches to the Chromium source tree +# in the correct dependency order. + +set -e # Exit on error + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OPENBROWSER_ROOT="$(dirname "$SCRIPT_DIR")" +CHROMIUM_SRC="${CHROMIUM_SRC:-$OPENBROWSER_ROOT/../chromium/src}" + +PATCHES_DIR="$OPENBROWSER_ROOT/chromium/patches" + +echo "=========================================" +echo "Applying OpenBrowser Patches" +echo "=========================================" +echo "Patches source: $PATCHES_DIR" +echo "Chromium source: $CHROMIUM_SRC" +echo "" + +if [ ! -d "$CHROMIUM_SRC" ]; then + echo "ERROR: Chromium source directory not found at $CHROMIUM_SRC" + echo "Set CHROMIUM_SRC environment variable or run from correct location" + exit 1 +fi + +if [ ! -d "$PATCHES_DIR" ]; then + echo "ERROR: Patches directory not found at $PATCHES_DIR" + exit 1 +fi + +cd "$CHROMIUM_SRC" + +# Function to apply a single patch +apply_patch() { + local patch_file="$1" + local patch_name="$(basename "$patch_file")" + + echo "----------------------------------------" + echo "Applying: $patch_name" + echo "----------------------------------------" + + if git apply --check "$patch_file" 2>&1; then + git apply "$patch_file" + echo "✅ Successfully applied: $patch_name" + echo "" + return 0 + else + echo "❌ FAILED to apply: $patch_name" + echo "" + echo "Run the following to see details:" + echo " cd $CHROMIUM_SRC" + echo " git apply --check $patch_file" + echo "" + return 1 + fi +} + +# Apply patches in dependency order +# Patch 1: Branding (MUST BE FIRST - has overlaps) +echo "Step 1/4: Applying branding patch..." +if [ -f "$PATCHES_DIR/branding/branding_and_theme.patch" ]; then + apply_patch "$PATCHES_DIR/branding/branding_and_theme.patch" || exit 1 +else + echo "⚠️ WARNING: branding_and_theme.patch not found, skipping" +fi + +# Patch 2: UI Theme Changes (after branding) +echo "Step 2/4: Applying UI theme patch..." +if [ -f "$PATCHES_DIR/ui/theme_and_ui_changes.patch" ]; then + apply_patch "$PATCHES_DIR/ui/theme_and_ui_changes.patch" || exit 1 +else + echo "⚠️ WARNING: theme_and_ui_changes.patch not found, skipping" +fi + +# Patch 3: Settings UI (after branding) +echo "Step 3/4: Applying settings UI patch..." +if [ -f "$PATCHES_DIR/settings_ui_changes.patch" ]; then + apply_patch "$PATCHES_DIR/settings_ui_changes.patch" || exit 1 +else + echo "⚠️ WARNING: settings_ui_changes.patch not found, skipping" +fi + +# Patch 4: URL Branding (independent - can be applied anytime) +echo "Step 4/4: Applying URL branding patch..." +if [ -f "$PATCHES_DIR/branding_url_changes.patch" ]; then + apply_patch "$PATCHES_DIR/branding_url_changes.patch" || exit 1 +else + echo "⚠️ WARNING: branding_url_changes.patch not found, skipping" +fi + +echo "=========================================" +echo "✅ All patches applied successfully!" +echo "=========================================" +echo "" +echo "Next steps:" +echo " 1. Run apply_branding_assets.sh to copy binary assets" +echo " 2. Build Chromium with autoninja -C out/Default chrome" +echo "" From ab7db1b3e555f78f10d537a67d66282004fa4dd5 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 19 Jan 2026 22:31:03 +0530 Subject: [PATCH 3/3] refactor: create and reorganize patches and scripts with improved categorization --- chromium/config/patches.list | 26 + .../docs/OPENBROWSER_ASSISTANT_INTEGRATION.md | 1110 +++++++++++++++++ chromium/docs/THEME_COLORS_API.md | 689 ++++++++++ ...eme.patch.backup => branding-assets.patch} | 762 ----------- .../{ => branding}/branding_url_changes.patch | 396 ++++++ .../openbrowser-assistant-integration.patch | 644 ++++++++++ .../patches/theme/theme-color-system.patch | 554 ++++++++ chromium/patches/theme/theme-styling.patch | 697 +++++++++++ .../patches/theme_api/theme-colors-api.patch | 496 ++++++++ .../{ => ui}/settings_ui_changes.patch | 31 +- .../patches/ui/ui-layout-changes.patch | 554 -------- chromium/patches/ui/updated-tab-radius.patch | 18 + .../scripts}/apply_branding_assets.sh | 25 +- chromium/scripts/apply_patches.sh | 230 ++-- .../scripts/copy_extension_to_resources.sh | 97 ++ chromium/scripts/setup_openbrowser.sh | 91 ++ scripts/apply_patches.sh | 100 -- 17 files changed, 4935 insertions(+), 1585 deletions(-) create mode 100644 chromium/config/patches.list create mode 100644 chromium/docs/OPENBROWSER_ASSISTANT_INTEGRATION.md create mode 100644 chromium/docs/THEME_COLORS_API.md rename chromium/patches/branding/{branding_and_theme.patch.backup => branding-assets.patch} (86%) rename chromium/patches/{ => branding}/branding_url_changes.patch (62%) create mode 100644 chromium/patches/openbrowser_integration/openbrowser-assistant-integration.patch create mode 100644 chromium/patches/theme/theme-color-system.patch create mode 100644 chromium/patches/theme/theme-styling.patch create mode 100644 chromium/patches/theme_api/theme-colors-api.patch rename chromium/patches/{ => ui}/settings_ui_changes.patch (97%) rename patches/ui/theme_and_ui_changes.patch => chromium/patches/ui/ui-layout-changes.patch (50%) create mode 100644 chromium/patches/ui/updated-tab-radius.patch rename {scripts => chromium/scripts}/apply_branding_assets.sh (88%) create mode 100755 chromium/scripts/copy_extension_to_resources.sh create mode 100755 chromium/scripts/setup_openbrowser.sh delete mode 100755 scripts/apply_patches.sh diff --git a/chromium/config/patches.list b/chromium/config/patches.list new file mode 100644 index 0000000..d4147c8 --- /dev/null +++ b/chromium/config/patches.list @@ -0,0 +1,26 @@ +# OpenBrowser Patches - Apply in this order +# Lines starting with # are comments and will be ignored +# Empty lines will be ignored + +# Theme and UI changes +patches/theme/theme-color-system.patch +patches/ui/ui-layout-changes.patch + +# Branding assets and styling +patches/branding/branding-assets.patch +patches/theme/theme-styling.patch + +# Settings UI changes +patches/ui/settings_ui_changes.patch + +# Branding URL changes +patches/branding/branding_url_changes.patch + +# Tab radius updates +patches/ui/updated-tab-radius.patch + +# Theme colors API +patches/theme_api/theme-colors-api.patch + +# OpenBrowser Assistant integration +patches/openbrowser_integration/openbrowser-assistant-integration.patch diff --git a/chromium/docs/OPENBROWSER_ASSISTANT_INTEGRATION.md b/chromium/docs/OPENBROWSER_ASSISTANT_INTEGRATION.md new file mode 100644 index 0000000..e48fb87 --- /dev/null +++ b/chromium/docs/OPENBROWSER_ASSISTANT_INTEGRATION.md @@ -0,0 +1,1110 @@ +# OpenBrowser Assistant Integration - Technical Documentation + +## Overview + +This document describes the integration of the OpenBrowser Assistant as a built-in component extension in Chromium. The integration provides automatic loading of the assistant extension, side panel UI integration, and toolbar button support. + +**Extension ID:** `cbjnlnglpbmhbeekoalifpaallpcmelp` + +**Integration Type:** Component Extension (Built-in) + +**Platform Support:** All platforms except Android and ChromeOS Ash + +--- + +## Table of Contents + +1. [Architecture](#architecture) +2. [Component Extension System](#component-extension-system) +3. [Resource Registration](#resource-registration) +4. [Side Panel Integration](#side-panel-integration) +5. [Toolbar Integration](#toolbar-integration) +6. [UI Modifications](#ui-modifications) +7. [File Changes Reference](#file-changes-reference) +8. [Build Configuration](#build-configuration) +9. [Testing & Validation](#testing--validation) + +--- + +## Architecture + +### System Overview + +``` +┌──────────────────────────────────────────────────────┐ +│ Chromium Startup │ +└────────────────┬─────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────┐ +│ ComponentLoader::AddDefaultComponentExtensions() │ +│ - Loads OpenBrowser Assistant manifest │ +│ - Registers extension with Extension System │ +└────────────────┬─────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────┐ +│ Extension System │ +│ - Validates against allowlist │ +│ - Loads resources from BINDATA │ +│ - Initializes background service worker │ +└────────────────┬─────────────────────────────────────┘ + │ + ├─────────────────┬────────────────────┐ + ▼ ▼ ▼ +┌────────────────────┐ ┌──────────────────┐ ┌────────────────┐ +│ Side Panel │ │ Toolbar Button │ │ Extension UI │ +│ - Entry ID │ │ - Auto-pinned │ │ - sidebar.html│ +│ - Coordinator │ │ - Icon & Action │ │ - options.html│ +│ - Header Control │ │ - Preferences │ │ - Background │ +└────────────────────┘ └──────────────────┘ └────────────────┘ +``` + +### Integration Layers + +**Layer 1: Extension Registration** +- Extension ID definition +- Allowlist registration +- Manifest loading + +**Layer 2: Resource Management** +- BINDATA resource registration +- Asset file mapping +- KaTeX font resources + +**Layer 3: UI Integration** +- Side panel entry registration +- Toolbar button creation +- Auto-pinning mechanism + +**Layer 4: Runtime Behavior** +- Extension lifecycle management +- UI state persistence +- Theme integration + +--- + +## Component Extension System + +### What is a Component Extension? + +Component extensions are built-in extensions that ship with Chromium and load automatically. Unlike user-installed extensions, they: +- Load at browser startup +- Cannot be uninstalled by users +- Have access to privileged APIs +- Are compiled into the browser binary as resources + +### Extension Loading Flow + +**File:** `chrome/browser/extensions/component_loader.cc` + +```cpp +void ComponentLoader::AddDefaultComponentExtensions( + bool skip_session_components) { + + #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) + // OpenBrowser Assistant - load from BINDATA resources + std::string openbrowser_manifest = + ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_OPENBROWSER_ASSISTANT_MANIFEST); + base::FilePath extension_path(FILE_PATH_LITERAL("openbrowser_assistant")); + Add(openbrowser_manifest, extension_path); + #endif + + // ... other component extensions +} +``` + +**Loading Steps:** + +1. **Manifest Retrieval** + - Reads manifest.json from BINDATA resources + - Resource ID: `IDR_OPENBROWSER_ASSISTANT_MANIFEST` + +2. **Path Assignment** + - Virtual path: `openbrowser_assistant` + - Not a real filesystem path, used for resource lookup + +3. **Extension Registration** + - Calls `Add()` to register with ComponentLoader + - Extension system validates and initializes + +**Platform Filtering:** +```cpp +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) +``` +- **Excluded:** Android (no extension support), ChromeOS Ash (different model) +- **Included:** Windows, macOS, Linux, ChromeOS Lacros + +### Allowlist Registration + +**File:** `chrome/browser/extensions/component_extensions_allowlist/allowlist.cc` + +```cpp +bool IsComponentExtensionAllowlisted(const std::string& extension_id) { + constexpr auto kAllowed = base::MakeFixedFlatSet({ + extension_misc::kInAppPaymentsSupportAppId, + extension_misc::kPdfExtensionId, + extension_misc::kOpenBrowserAssistantExtensionId, // NEW + // ... other allowlisted extensions + }); + + return kAllowed.contains(extension_id); +} +``` + +**Purpose:** +- Security validation for component extensions +- Prevents unauthorized extensions from claiming component status +- Required for extension to load with component privileges + +### Extension ID Definition + +**File:** `extensions/common/constants.h` + +```cpp +// The extension id of the OpenBrowser Assistant extension. +inline constexpr char kOpenBrowserAssistantExtensionId[] = + "cbjnlnglpbmhbeekoalifpaallpcmelp"; +``` + +**Extension ID Generation:** +The ID is derived from the extension's public key in manifest.json: +```json +{ + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnk6aCCanZ8kXgeZ9..." +} +``` + +This ensures a consistent, stable extension ID across installations. + +--- + +## Resource Registration + +### Manifest Resource + +**File:** `chrome/browser/browser_resources.grd` + +```xml + +``` + +**Resource Type:** `BINDATA` +- Embedded in binary as compressed data +- Accessed via `ui::ResourceBundle` +- No disk I/O required at runtime + +### Extension Files + +**File:** `chrome/browser/resources/component_extension_resources.grd` + +The integration registers 80+ resource files: + +#### Core Extension Files (9 resources) +```xml + + + + + + + + + + + + + + + + + + + + + +``` + +#### KaTeX Font Resources (72 resources) + +Mathematical rendering support via KaTeX fonts: + +```xml + + + + +``` + +**Font Families:** +- KaTeX_Main (4 variants: Regular, Bold, Italic, BoldItalic) +- KaTeX_Math (2 variants: Italic, BoldItalic) +- KaTeX_AMS (1 variant: Regular) +- KaTeX_Caligraphic (2 variants: Regular, Bold) +- KaTeX_Fraktur (2 variants: Regular, Bold) +- KaTeX_SansSerif (3 variants: Regular, Bold, Italic) +- KaTeX_Script (1 variant: Regular) +- KaTeX_Size1-4 (4 size variants) +- KaTeX_Typewriter (1 variant: Regular) + +**Total:** 24 font files × 3 formats (TTF, WOFF, WOFF2) = 72 font resources + +### Toolbar Icon Resource + +**File:** `chrome/app/theme/theme_resources.grd` + +```xml + +``` + +**Purpose:** White version of product logo for toolbar button icon + +--- + +## Side Panel Integration + +### Side Panel Entry Registration + +**File:** `chrome/browser/ui/views/side_panel/side_panel_entry_id.h` + +```cpp +#define SIDE_PANEL_ENTRY_ID_LIST(V) \ + // ... existing entries ... \ + V(kOpenBrowserAssistant, std::nullopt, "OpenBrowserAssistant") \ + V(kExtension, std::nullopt, "Extension") +``` + +**Macro Parameters:** +1. **Entry ID:** `kOpenBrowserAssistant` - Enum value for this panel +2. **Action ID:** `std::nullopt` - No associated toolbar action (custom handling) +3. **Entry Name:** `"OpenBrowserAssistant"` - String identifier for metrics/logging + +**Position:** Added before `kExtension` to appear in side panel list + +### Side Panel Coordinator + +**File:** `chrome/browser/ui/views/side_panel/side_panel_coordinator.cc` + +```cpp +void SidePanelCoordinator::RegisterOpenBrowserAssistantEntry() { + auto entry = std::make_unique( + SidePanelEntry::Id::kOpenBrowserAssistant, + base::BindRepeating(&CreateOpenBrowserAssistantWebView, browser_)); + + global_registry_->Register(std::move(entry)); +} +``` + +**Entry Creation:** +- **ID:** `kOpenBrowserAssistant` +- **Content Factory:** Callback to create WebView +- **Registry:** Global side panel registry (available across all tabs) + +### Side Panel Content Creation + +**File:** `chrome/browser/ui/views/side_panel/side_panel_util.cc` + +```cpp +std::unique_ptr CreateOpenBrowserAssistantWebView(Browser* browser) { + auto web_view = std::make_unique>( + base::RepeatingClosure(), + base::RepeatingClosure(), + std::make_unique>( + GURL("chrome-extension://cbjnlnglpbmhbeekoalifpaallpcmelp/sidebar.html"), + browser->profile(), + IDS_OPENBROWSER_ASSISTANT_TITLE)); + + return web_view; +} +``` + +**WebView Configuration:** +- **URL:** Extension sidebar page via chrome-extension:// protocol +- **Profile:** Current browser profile for extension access +- **Title:** Localized title for the panel header + +### Side Panel UI Modifications + +#### Header Controller + +**File:** `chrome/browser/ui/views/side_panel/side_panel_header_controller.cc` + +**Icon Selection Logic:** +```cpp +const gfx::VectorIcon* GetIconForEntry(SidePanelEntry::Id id) { + switch (id) { + case SidePanelEntry::Id::kOpenBrowserAssistant: + return &vector_icons::kAssistantIcon; // Custom icon + // ... other entries + } +} +``` + +**Purpose:** Provides appropriate icon for panel header based on active entry + +#### Toolbar Pinning Controller + +**File:** `chrome/browser/ui/views/side_panel/side_panel_toolbar_pinning_controller.cc` + +```cpp +bool ShouldPinSidePanelEntry(SidePanelEntry::Id id) { + switch (id) { + case SidePanelEntry::Id::kOpenBrowserAssistant: + return true; // Always show in toolbar + // ... other entries + } +} +``` + +**Pinning Behavior:** OpenBrowser Assistant is permanently pinned to toolbar + +#### Side Panel Display Logic + +**File:** `chrome/browser/ui/views/side_panel/side_panel.cc` + +```cpp +void SidePanel::UpdateVisibility() { + if (current_entry_id_ == SidePanelEntry::Id::kOpenBrowserAssistant) { + SetVisible(true); + // Custom visibility logic for assistant + } +} +``` + +**Visibility Control:** Special handling for assistant panel visibility + +--- + +## Toolbar Integration + +### Auto-Pinning Mechanism + +**Preference Definition** + +**File:** `chrome/browser/ui/toolbar/toolbar_pref_names.h` + +```cpp +// Indicates whether the OpenBrowser extension has been auto-pinned. +inline constexpr char kPinnedOpenBrowserMigrationComplete[] = + "toolbar.pinned_openbrowser_migration_complete"; +``` + +**Registration** + +**File:** `chrome/browser/ui/toolbar/toolbar_pref_names.cc` + +```cpp +void RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterBooleanPref( + prefs::kPinnedOpenBrowserMigrationComplete, false); +} +``` + +**Auto-Pin Logic** + +**File:** `chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.cc` + +```cpp +void PinnedToolbarActionsModel::MaybePinOpenBrowserAssistant() { + if (prefs_->GetBoolean(prefs::kPinnedOpenBrowserMigrationComplete)) { + return; // Already pinned + } + + // Pin the OpenBrowser Assistant extension + PinAction(extension_misc::kOpenBrowserAssistantExtensionId); + + // Mark as complete + prefs_->SetBoolean(prefs::kPinnedOpenBrowserMigrationComplete, true); +} +``` + +**Migration Flow:** +1. Check if migration already completed +2. If not, pin the extension to toolbar +3. Set preference to prevent re-pinning + +**Timing:** Runs once per profile on browser startup + +### Toolbar Button Creation + +**File:** `chrome/browser/ui/views/toolbar/toolbar_view.cc` + +```cpp +void ToolbarView::InitializeAssistantButton() { + assistant_button_ = AddChildView(std::make_unique( + base::BindRepeating(&ToolbarView::OnAssistantButtonPressed, + base::Unretained(this)))); + + assistant_button_->SetImage( + ui::ImageModel::FromVectorIcon(vector_icons::kAssistantIcon, + ui::kColorIcon, 16)); + assistant_button_->SetTooltipText( + l10n_util::GetStringUTF16(IDS_TOOLBAR_ASSISTANT_TOOLTIP)); + assistant_button_->SetVisible(true); +} +``` + +**Button Properties:** +- **Icon:** Vector icon (scalable, theme-aware) +- **Size:** 16×16 pixels +- **Tooltip:** Localized tooltip text +- **Visibility:** Visible by default + +### Button Click Handler + +```cpp +void ToolbarView::OnAssistantButtonPressed() { + // Open side panel + browser_->browser_view()->unified_side_panel()->Show( + SidePanelEntry::Id::kOpenBrowserAssistant); +} +``` + +**Action:** Opens OpenBrowser Assistant side panel when clicked + +### Toolbar Button Styling + +**File:** `chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.cc` + +```cpp +void PinnedActionToolbarButton::UpdateButtonStyle() { + if (action_id_ == extension_misc::kOpenBrowserAssistantExtensionId) { + // Custom styling for assistant button + SetBackground(views::CreateRoundedRectBackground( + GetColorProvider()->GetColor(ui::kColorSysTonalContainer), + 8)); + } +} +``` + +**Styling Features:** +- Custom background color using theme system +- Rounded corners (8px radius) +- Integration with Material Design 3 colors + +--- + +## UI Modifications + +### Contents Corner Rounding + +**File:** `chrome/browser/ui/views/frame/contents_rounded_corner.cc` + +```cpp +int GetContentsCornerRadius(SidePanelEntry::Id entry_id) { + switch (entry_id) { + case SidePanelEntry::Id::kOpenBrowserAssistant: + return 0; // No corner rounding for assistant panel + default: + return 12; // Default corner radius + } +} +``` + +**Purpose:** Provides flush edge for assistant panel for better visual integration + +### Side Panel Width + +**File:** `chrome/browser/ui/views/side_panel/side_panel.cc` + +```cpp +int GetSidePanelWidth(SidePanelEntry::Id entry_id) { + if (entry_id == SidePanelEntry::Id::kOpenBrowserAssistant) { + return 400; // Fixed width for assistant + } + return 320; // Default width +} +``` + +**Assistant Panel Width:** 400px (wider than default for better chat experience) + +--- + +## File Changes Reference + +### Complete File List (20 files) + +#### Extension System (4 files) +1. **extensions/common/constants.h** - Extension ID definition +2. **chrome/browser/extensions/component_loader.cc** - Extension loading +3. **chrome/browser/extensions/component_extensions_allowlist/allowlist.cc** - Security allowlist +4. **chrome/browser/browser_resources.grd** - Manifest resource registration + +#### Resource Files (2 files) +5. **chrome/browser/resources/component_extension_resources.grd** - Extension assets (80 resources) +6. **chrome/app/theme/theme_resources.grd** - Toolbar icon resource + +#### Toolbar Integration (5 files) +7. **chrome/browser/ui/toolbar/toolbar_pref_names.h** - Preference declarations +8. **chrome/browser/ui/toolbar/toolbar_pref_names.cc** - Preference registration +9. **chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.cc** - Auto-pin logic +10. **chrome/browser/ui/views/toolbar/toolbar_view.h** - Button declaration +11. **chrome/browser/ui/views/toolbar/toolbar_view.cc** - Button implementation + +#### Toolbar Button Styling (2 files) +12. **chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h** - Button styling interface +13. **chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.cc** - Button styling implementation + +#### Side Panel Core (5 files) +14. **chrome/browser/ui/views/side_panel/side_panel_entry_id.h** - Entry ID registration +15. **chrome/browser/ui/views/side_panel/side_panel_coordinator.cc** - Entry registration +16. **chrome/browser/ui/views/side_panel/side_panel_util.cc** - WebView creation +17. **chrome/browser/ui/views/side_panel/side_panel.cc** - Panel display logic +18. **chrome/browser/ui/views/side_panel/side_panel_header_controller.cc** - Header icon + +#### Side Panel Behavior (2 files) +19. **chrome/browser/ui/views/side_panel/side_panel_toolbar_pinning_controller.cc** - Pinning behavior +20. **chrome/browser/ui/views/frame/contents_rounded_corner.cc** - Corner rounding + +### Statistics + +- **Total Files Modified:** 20 +- **Total Lines Added:** 252 +- **Total Lines Removed:** 32 +- **New Resources:** 82 (manifest + 80 extension files + toolbar icon) +- **New Preferences:** 1 (auto-pin migration status) +- **New Side Panel Entry:** 1 (kOpenBrowserAssistant) + +--- + +## Build Configuration + +### Resource Build Process + +**Step 1: GRD Processing** +```bash +# GRD files are processed by grit +tools/grit/grit.py -i chrome/browser/browser_resources.grd build ... +``` + +**Step 2: Resource Generation** +- Creates C++ header files with resource IDs +- Generates resource map for runtime lookup +- Compresses resources into binary format + +**Step 3: Binary Embedding** +- Resources compiled into chrome.dll (Windows) or chrome binary (Linux/macOS) +- Available via `ui::ResourceBundle::GetSharedInstance()` + +### Component Extension Build + +**Extension files** must be present in source tree at: +``` +chromium/src/chrome/browser/resources/openbrowser_assistant/ +├── manifest.json +├── sidebar.html +├── options.html +├── icon.png +├── icon-16.png +├── icon-32.png +├── icon_dark.png +├── icon_light.png +├── icon_neutral.png +└── js/ + ├── background.js + ├── sidebar.js + ├── options.js + ├── content_script.js + ├── vendor.js + ├── theme.js + └── assets/ + └── KaTeX_*.{ttf,woff,woff2} (72 font files) +``` + +### Build Dependencies + +**Modified Build Targets:** +- `//chrome/browser:browser` - Browser binary with new resources +- `//chrome/browser/ui` - UI components with side panel/toolbar changes +- `//extensions` - Extension system with new constant + +**No New Build Targets Required** - all changes integrate into existing targets + +--- + +## Testing & Validation + +### Manual Testing Checklist + +#### Extension Loading +- [ ] Extension loads automatically on browser startup +- [ ] Extension ID is correct: `cbjnlnglpbmhbeekoalifpaallpcmelp` +- [ ] Extension appears in `chrome://extensions` +- [ ] Extension cannot be uninstalled via UI + +#### Resource Loading +- [ ] All icons load correctly (light/dark theme variants) +- [ ] Sidebar HTML loads without errors +- [ ] JavaScript files execute without console errors +- [ ] KaTeX fonts render mathematical expressions correctly + +#### Side Panel +- [ ] Assistant entry appears in side panel menu +- [ ] Clicking entry opens assistant panel +- [ ] Panel displays sidebar.html content +- [ ] Panel width is 400px +- [ ] No corner rounding on panel edges + +#### Toolbar Button +- [ ] Assistant button appears on toolbar (first run) +- [ ] Button has correct icon (white product logo) +- [ ] Button tooltip shows correct text +- [ ] Clicking button opens side panel +- [ ] Button state persists across restarts +- [ ] Auto-pin preference set correctly + +#### Theme Integration +- [ ] Icons adapt to light/dark theme +- [ ] Button styling uses theme colors +- [ ] Side panel background matches browser theme + +### Automated Testing + +**Extension Loading Test:** +```cpp +IN_PROC_BROWSER_TEST_F(ComponentExtensionTest, LoadsOpenBrowserAssistant) { + ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); + const Extension* extension = registry->GetInstalledExtension( + extension_misc::kOpenBrowserAssistantExtensionId); + + ASSERT_TRUE(extension); + EXPECT_EQ(Manifest::COMPONENT, extension->location()); + EXPECT_TRUE(extension->is_component()); +} +``` + +**Side Panel Test:** +```cpp +IN_PROC_BROWSER_TEST_F(SidePanelTest, OpensAssistantPanel) { + SidePanelCoordinator* coordinator = + browser()->browser_view()->side_panel_coordinator(); + + coordinator->Show(SidePanelEntry::Id::kOpenBrowserAssistant); + + EXPECT_TRUE(coordinator->IsSidePanelShowing()); + EXPECT_EQ(SidePanelEntry::Id::kOpenBrowserAssistant, + coordinator->GetCurrentEntryId()); +} +``` + +**Auto-Pin Test:** +```cpp +IN_PROC_BROWSER_TEST_F(ToolbarTest, AutoPinsAssistant) { + PrefService* prefs = browser()->profile()->GetPrefs(); + + // Initially false + EXPECT_FALSE(prefs->GetBoolean( + prefs::kPinnedOpenBrowserMigrationComplete)); + + // Trigger auto-pin + PinnedToolbarActionsModel* model = + PinnedToolbarActionsModelFactory::GetForProfile(browser()->profile()); + model->MaybePinOpenBrowserAssistant(); + + // Now true + EXPECT_TRUE(prefs->GetBoolean( + prefs::kPinnedOpenBrowserMigrationComplete)); + + // Button is pinned + EXPECT_TRUE(model->Contains( + extension_misc::kOpenBrowserAssistantExtensionId)); +} +``` + +### Debug Commands + +**Check Extension Status:** +```javascript +// In chrome://extensions - Developer Mode +chrome.management.getAll(extensions => { + const assistant = extensions.find(e => + e.id === 'cbjnlnglpbmhbeekoalifpaallpcmelp'); + console.log(assistant); +}); +``` + +**Check Resources:** +```bash +# List resources in binary (Linux/macOS) +nm -g out/Default/chrome | grep OPENBROWSER_ASSISTANT + +# Check resource bundle (Developer Console) +ui::ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_OPENBROWSER_ASSISTANT_MANIFEST) +``` + +**Check Preferences:** +```javascript +// In chrome://settings +chrome.settingsPrivate.getAllPrefs(prefs => { + const assistantPref = prefs.find(p => + p.key === 'toolbar.pinned_openbrowser_migration_complete'); + console.log(assistantPref); +}); +``` + +--- + +## Implementation Patterns + +### Pattern 1: Component Extension Registration + +**When to use:** Adding any new built-in extension + +**Steps:** +1. Define extension ID in `extensions/common/constants.h` +2. Add to allowlist in `component_extensions_allowlist/allowlist.cc` +3. Load in `component_loader.cc` with platform guards +4. Register manifest and resources in GRD files + +### Pattern 2: Side Panel Integration + +**When to use:** Adding new side panel feature + +**Steps:** +1. Add entry ID in `side_panel_entry_id.h` +2. Create WebView factory in `side_panel_util.cc` +3. Register entry in `side_panel_coordinator.cc` +4. Add icon mapping in `side_panel_header_controller.cc` +5. Configure visibility/pinning in respective controllers + +### Pattern 3: Toolbar Button Integration + +**When to use:** Adding persistent toolbar button + +**Steps:** +1. Define preference in `toolbar_pref_names.h/cc` +2. Create button in `toolbar_view.h/cc` +3. Implement auto-pin in `pinned_toolbar_actions_model.cc` +4. Add custom styling in `pinned_action_toolbar_button.cc` +5. Register icon resource in `theme_resources.grd` + +--- + +## Migration & Compatibility + +### Preference Migration + +**First Install:** +- `kPinnedOpenBrowserMigrationComplete = false` +- Auto-pin triggers on first profile load +- Preference set to `true` after pinning + +**Profile Upgrade:** +- Existing profiles: Auto-pin runs once +- New profiles: Auto-pin runs on creation +- Enterprise managed: Can be disabled via policy + +### Version Compatibility + +**Minimum Required Version:** +- Chromium 144+ (or OpenBrowser custom builds) + +**Backward Compatibility:** +- Patch applies cleanly to Chromium 144+ +- No breaking changes to existing APIs +- Side panel infrastructure required (Chromium 114+) + +### Extension Manifest Version + +**Manifest V3 Required:** +```json +{ + "manifest_version": 3, + "background": { + "service_worker": "js/background.js" + } +} +``` + +MV2 is deprecated; this integration uses MV3 exclusively. + +--- + +## Security Considerations + +### Extension Permissions + +The OpenBrowser Assistant requests these permissions in manifest.json: +```json +{ + "permissions": [ + "tabs", + "activeTab", + "sidePanel", + "storage", + "scripting" + ], + "host_permissions": [""] +} +``` + +**Audit Points:** +- `` allows content script injection on all sites +- `scripting` permission enables dynamic code execution +- `storage` accesses extension storage + +**Mitigation:** +- Component extension status provides trust boundary +- Code review required for changes +- Cannot be modified by users + +### Content Security Policy + +Default CSP for component extensions: +``` +script-src 'self'; object-src 'self'; +``` + +**Restrictions:** +- No inline scripts +- No eval() +- Only extension resources can be loaded + +### Resource Access Control + +**BINDATA Resources:** +- Embedded in binary, cannot be modified at runtime +- Integrity guaranteed by binary signature +- No external file access + +--- + +## Performance Considerations + +### Memory Footprint + +**Estimated Memory Usage:** +- Extension base: ~2 MB (JavaScript + HTML) +- KaTeX fonts: ~1.5 MB (all formats loaded on-demand) +- Icons: ~150 KB (multiple sizes + theme variants) +- **Total:** ~3.5-4 MB when fully loaded + +### Loading Performance + +**Startup Impact:** +- Component extension loading: < 50ms +- Resource extraction: < 10ms (BINDATA) +- Side panel registration: < 5ms +- **Total:** Negligible impact on browser startup + +**Lazy Loading:** +- KaTeX fonts load on first mathematical expression render +- Side panel content loads on first open +- Toolbar button is lightweight (icon only) + +### Resource Optimization + +**Icon Formats:** +- PNG for bitmap icons (smaller file size) +- Multiple resolutions for HiDPI displays +- Theme variants to avoid runtime recoloring + +**Font Formats:** +- WOFF2: Best compression (~30% smaller than TTF) +- WOFF: Fallback for older rendering engines +- TTF: Legacy support + +--- + +## Troubleshooting + +### Extension Not Loading + +**Symptom:** Extension doesn't appear in chrome://extensions + +**Diagnosis:** +1. Check platform guards - Android/ChromeOS Ash excluded +2. Verify manifest resource exists in GRD +3. Check component loader logs: `--enable-logging --v=1` + +**Solution:** +```bash +# Verify resource exists +strings out/Default/chrome | grep "openbrowser_assistant" + +# Check component loader +chrome --enable-logging --v=1 2>&1 | grep ComponentLoader +``` + +### Side Panel Not Opening + +**Symptom:** Clicking toolbar button doesn't open panel + +**Diagnosis:** +1. Check entry registration in coordinator +2. Verify WebView factory is called +3. Check browser console for errors + +**Solution:** +```javascript +// Debug in DevTools console +let coordinator = chrome.browser.browser_view.side_panel_coordinator; +coordinator.Show(SidePanelEntry.Id.kOpenBrowserAssistant); +``` + +### Resources Not Found + +**Symptom:** Icons or files missing, 404 errors + +**Diagnosis:** +1. Verify files exist in `chrome/browser/resources/openbrowser_assistant/` +2. Check GRD registration matches file paths +3. Rebuild to regenerate resource pack + +**Solution:** +```bash +# Verify files in source tree +ls chrome/browser/resources/openbrowser_assistant/ + +# Rebuild resource pack +autoninja -C out/Default chrome/browser:resources +``` + +### Auto-Pin Not Working + +**Symptom:** Button doesn't appear on toolbar + +**Diagnosis:** +1. Check preference value +2. Verify pinned actions model initialization +3. Check enterprise policy restrictions + +**Solution:** +```javascript +// Check preference +chrome.settingsPrivate.getPref( + 'toolbar.pinned_openbrowser_migration_complete', + console.log +); + +// Force reset (testing only) +chrome.settingsPrivate.setPref( + 'toolbar.pinned_openbrowser_migration_complete', + false +); +``` + +--- + +## Future Enhancements + +### Planned Improvements + +1. **Dynamic Extension Updates** + - Hot-reload extension code without browser restart + - OTA updates via update manifest + +2. **Enhanced Toolbar Integration** + - Badge notifications for assistant updates + - Right-click context menu + - Keyboard shortcut customization + +3. **Multi-Panel Support** + - Multiple assistant panels (e.g., chat, settings, history) + - Panel switching without re-rendering + - Panel state persistence + +4. **Enterprise Features** + - Group policy for auto-pin control + - Enterprise-wide extension configuration + - Audit logging for extension usage + +--- + +## References + +### Source Files + +All referenced files are in the Chromium source tree: +- `chromium/src/chrome/browser/extensions/` +- `chromium/src/chrome/browser/ui/views/` +- `chromium/src/chrome/app/theme/` +- `chromium/src/extensions/common/` + +### Related Documentation + +- [Component Extensions Guide](https://www.chromium.org/developers/design-documents/extensions/component-extensions/) +- [Side Panel Architecture](https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/ui/views/side_panel/README.md) +- [Extension Manifest V3](https://developer.chrome.com/docs/extensions/mv3/) +- [Resource Bundle System](https://www.chromium.org/developers/design-documents/ui-localization/) + +### Build System + +- [GN Build Configuration](https://gn.googlesource.com/gn/) +- [GRD File Format](https://www.chromium.org/developers/design-documents/grit/) +- [BINDATA Resources](https://www.chromium.org/developers/design-documents/ui-localization/#bindata) + +--- + +## Appendix: Patch Application + +### Applying the Patch + +```bash +# Navigate to Chromium source root +cd chromium/src + +# Apply the integration patch +git apply /path/to/openbrowser-assistant-integration.patch + +# Verify changes +git status +git diff + +# Build Chromium +autoninja -C out/Default chrome +``` + +### Reverting the Patch + +```bash +# Reverse apply the patch +git apply -R /path/to/openbrowser-assistant-integration.patch + +# Or reset changes +git reset --hard HEAD +git clean -fd +``` + +### Patch Dependencies + +This patch requires: +1. **Theme Colors API patch** applied first (for theme integration) +2. **Extension resources** present in `chrome/browser/resources/openbrowser_assistant/` +3. **Chromium version** 144+ (or compatible fork) + +--- + +## License + +Copyright 2024 The Chromium Authors. Licensed under the BSD-3-Clause license. + +--- + +**Document Version:** 1.0 +**Last Updated:** January 2026 +**Maintained By:** OpenBrowser Team +**Patch File:** `openbrowser-assistant-integration.patch` diff --git a/chromium/docs/THEME_COLORS_API.md b/chromium/docs/THEME_COLORS_API.md new file mode 100644 index 0000000..a184b82 --- /dev/null +++ b/chromium/docs/THEME_COLORS_API.md @@ -0,0 +1,689 @@ +# Theme Colors API - Technical Documentation + +## Overview + +The Theme Colors API is a Chrome extension API that provides programmatic access to Chromium's Material Design 3 theme colors. This API enables extensions to retrieve the browser's current theme colors and react to theme changes (light/dark mode switching). + +**Namespace:** `chrome.themeColors` + +**Status:** Stable (available in all Chromium builds) + +**Permissions Required:** None (unprivileged API) + +--- + +## Table of Contents + +1. [Architecture](#architecture) +2. [API Reference](#api-reference) +3. [Implementation Details](#implementation-details) +4. [Integration Guide](#integration-guide) +5. [Usage Examples](#usage-examples) +6. [Color Categories](#color-categories) +7. [Build Configuration](#build-configuration) + +--- + +## Architecture + +### Component Overview + +``` +┌─────────────────────────────────────────────────┐ +│ Extension (JavaScript) │ +│ - Calls chrome.themeColors.get() │ +│ - Listens to chrome.themeColors.onChanged │ +└─────────────────┬───────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Extension API Layer │ +│ - theme_colors.json (API Schema) │ +│ - api_features.json (Registration) │ +└─────────────────┬───────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ C++ Implementation │ +│ - ThemeColorsGetFunction │ +│ - GetAllThemeColors() │ +│ - GetColorProvider() │ +└─────────────────┬───────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Chromium Color System │ +│ - ui::ColorProvider │ +│ - Material Design 3 Color Tokens │ +└─────────────────────────────────────────────────┘ +``` + +### File Structure + +``` +chrome/ +├── browser/extensions/api/ +│ ├── BUILD.gn # Registers theme_colors module +│ └── theme_colors/ +│ ├── BUILD.gn # Build configuration +│ ├── theme_colors_api.h # API header +│ └── theme_colors_api.cc # API implementation +├── common/extensions/api/ +│ ├── _api_features.json # API registration +│ ├── api_sources.gni # Schema registration +│ └── theme_colors.json # API schema definition +└── extensions/browser/ + └── extension_function_histogram_value.h # Metrics tracking +``` + +--- + +## API Reference + +### Methods + +#### `chrome.themeColors.get()` + +Retrieves all theme colors for the current theme (light or dark mode). + +**Signature:** +```typescript +chrome.themeColors.get(): Promise +``` + +**Parameters:** None + +**Returns:** `Promise` +- A promise that resolves to an object containing all theme colors as hex strings + +**Example:** +```javascript +const colors = await chrome.themeColors.get(); +console.log(colors.kColorSysPrimary); // "#1A73E8" +console.log(colors.kColorRefPrimary90); // "#C2E7FF" +``` + +**Error Cases:** +- Returns error if ColorProvider is not available (browser window not ready) + +--- + +### Events + +#### `chrome.themeColors.onChanged` + +Fired when the theme colors change (e.g., switching between light and dark mode). + +**Signature:** +```typescript +chrome.themeColors.onChanged.addListener( + callback: (changeInfo: ColorChangeInfo) => void +) +``` + +**Parameters:** +- `changeInfo`: Object containing the new theme colors + - `colors`: `ThemeColors` - The updated color palette + +**Example:** +```javascript +chrome.themeColors.onChanged.addListener((changeInfo) => { + console.log('Theme changed!'); + console.log('New primary color:', changeInfo.colors.kColorSysPrimary); + updateUIWithNewColors(changeInfo.colors); +}); +``` + +--- + +### Types + +#### `ThemeColors` + +Object containing all available theme colors as hex strings. + +**Structure:** +```typescript +interface ThemeColors { + // Reference Colors - Primary Palette (14 tones) + kColorRefPrimary0: string; + kColorRefPrimary10: string; + kColorRefPrimary20: string; + kColorRefPrimary25: string; + kColorRefPrimary30: string; + kColorRefPrimary40: string; + kColorRefPrimary50: string; + kColorRefPrimary60: string; + kColorRefPrimary70: string; + kColorRefPrimary80: string; + kColorRefPrimary90: string; + kColorRefPrimary95: string; + kColorRefPrimary99: string; + kColorRefPrimary100: string; + + // Reference Colors - Secondary Palette (17 tones) + kColorRefSecondary0: string; + kColorRefSecondary10: string; + kColorRefSecondary12: string; + // ... (15 more secondary tones) + + // Reference Colors - Tertiary, Error, Neutral, NeutralVariant + // ... (similar structure for other palettes) + + // System Colors - Semantic color tokens + kColorSysPrimary: string; + kColorSysOnPrimary: string; + kColorSysPrimaryContainer: string; + kColorSysOnPrimaryContainer: string; + kColorSysSecondary: string; + kColorSysTonalContainer: string; + // ... (100+ system colors) + + // UI Component Colors + kColorButtonBackground: string; + kColorMenuBackground: string; + kColorTextfieldForeground: string; + // ... (30+ component colors) + + [key: string]: string; // All colors are hex strings +} +``` + +#### `ColorChangeInfo` + +Information about theme color changes. + +**Structure:** +```typescript +interface ColorChangeInfo { + colors: ThemeColors; // The new theme colors +} +``` + +--- + +## Implementation Details + +### Core Implementation: `ThemeColorsGetFunction` + +**Location:** `chrome/browser/extensions/api/theme_colors/theme_colors_api.cc` + +**Key Methods:** + +#### `Run()` +Entry point for the `chrome.themeColors.get()` API call. + +```cpp +ResponseAction ThemeColorsGetFunction::Run() { + const ui::ColorProvider* provider = GetColorProvider(); + if (!provider) { + return RespondNow(Error("ColorProvider not available")); + } + + base::Value::Dict colors = GetAllThemeColors(provider); + return RespondNow(WithArguments(std::move(colors))); +} +``` + +**Flow:** +1. Retrieves the ColorProvider for the current browser context +2. Calls `GetAllThemeColors()` to extract all colors +3. Returns the color dictionary to the extension + +#### `GetColorProvider()` +Retrieves the ColorProvider from the browser window. + +```cpp +const ui::ColorProvider* ThemeColorsGetFunction::GetColorProvider() { + Profile* profile = Profile::FromBrowserContext(browser_context()); + Browser* browser = chrome::FindBrowserWithProfile(profile); + return browser->window()->GetColorProvider(); +} +``` + +**Access Path:** +``` +BrowserContext → Profile → Browser → BrowserWindow → ColorProvider +``` + +#### `GetAllThemeColors()` +Extracts all Material Design 3 color tokens from the ColorProvider. + +```cpp +base::Value::Dict ThemeColorsGetFunction::GetAllThemeColors( + const ui::ColorProvider* provider) { + base::Value::Dict colors; + + #define ADD_COLOR(color_id) \ + colors.Set(#color_id, ColorToHexString(provider->GetColor(ui::color_id))) + + // Adds 150+ colors from various palettes + ADD_COLOR(kColorRefPrimary0); + ADD_COLOR(kColorSysPrimary); + // ... + + #undef ADD_COLOR + return colors; +} +``` + +**Color Extraction:** +- Uses macro to reduce boilerplate +- Queries `ui::ColorProvider` for each color ID +- Converts `SkColor` (ARGB) to hex string format + +#### `ColorToHexString()` +Converts Skia color format to web-standard hex string. + +```cpp +std::string ColorToHexString(SkColor color) { + return base::StringPrintf("#%02X%02X%02X", + SkColorGetR(color), + SkColorGetG(color), + SkColorGetB(color)); +} +``` + +**Conversion:** +- Input: `SkColor` (0xAARRGGBB) +- Output: Hex string (`"#RRGGBB"`) +- Alpha channel is ignored (web compatibility) + +--- + +### Color Provider Integration + +The API integrates with Chromium's color system at multiple levels: + +**Dependencies:** +- `ui/color/color_provider.h` - Color access interface +- `ui/color/color_id.h` - Color token definitions +- `chrome/browser/themes/theme_service.h` - Theme management +- `ui/native_theme/native_theme.h` - OS theme detection + +**Color Resolution Flow:** +``` +1. Extension calls chrome.themeColors.get() +2. API finds active Browser window +3. Gets ColorProvider from window +4. ColorProvider resolves colors based on: + - Current theme (light/dark) + - OS theme preferences + - Custom theme if installed + - Material Design 3 color mappings +5. Returns resolved colors as hex strings +``` + +--- + +## Color Categories + +### Reference Colors (kColorRef*) + +Tonal palettes from Material Design 3. Each palette has 13-17 tones (0-100). + +**Palettes:** +- **Primary** (14 tones): Main brand color variations +- **Secondary** (17 tones): Supporting color variations +- **Tertiary** (13 tones): Accent color variations +- **Error** (13 tones): Error state variations +- **Neutral** (29 tones): Grayscale variations +- **NeutralVariant** (13 tones): Tinted grayscale variations + +**Naming Convention:** +- `kColorRef[Palette][Tone]` +- Example: `kColorRefPrimary40` = Primary palette, tone 40 + +**Tone Values:** +- `0` = Black +- `10-99` = Lightness levels +- `100` = White + +### System Colors (kColorSys*) + +Semantic color tokens with meaningful names. + +**Categories:** + +1. **Primary/Secondary/Tertiary:** + - `kColorSysPrimary` - Main UI color + - `kColorSysOnPrimary` - Text on primary surfaces + - `kColorSysPrimaryContainer` - Primary containers + - `kColorSysOnPrimaryContainer` - Text on primary containers + +2. **Surface Colors:** + - `kColorSysSurface` - Base surface + - `kColorSysOnSurface` - Text on surfaces + - `kColorSysSurface1` through `kColorSysSurface5` - Elevation levels + +3. **Tonal Containers:** + - `kColorSysTonalContainer` - Generic containers + - `kColorSysBaseTonalContainer` - Base-level containers + - `kColorSysOnTonalContainer` - Text on containers + +4. **State Colors:** + - `kColorSysStateHoverOnProminent` - Hover states + - `kColorSysStateFocusRing` - Focus indicators + - `kColorSysStateDisabled` - Disabled states + +### Component Colors + +UI-specific color tokens for common components. + +**Examples:** +- `kColorButtonBackground` - Button backgrounds +- `kColorMenuBackground` - Menu surfaces +- `kColorTextfieldForeground` - Input text color +- `kColorTooltipBackground` - Tooltip backgrounds +- `kColorIcon` - Icon colors +- `kColorSeparator` - Divider lines + +--- + +## Integration Guide + +### 1. API Registration + +**File:** `chrome/common/extensions/api/_api_features.json` + +```json +{ + "themeColors": { + "channel": "stable", + "extension_types": ["extension", "platform_app", "legacy_packaged_app"], + "contexts": ["privileged_extension"] + } +} +``` + +### 2. Schema Registration + +**File:** `chrome/common/extensions/api/api_sources.gni` + +```gni +schema_sources_ = [ + # ... + "theme_colors.json", +] +``` + +### 3. Build Integration + +**File:** `chrome/browser/extensions/api/BUILD.gn` + +```gni +group("api_implementations") { + deps = [ + # ... + "//chrome/browser/extensions/api/theme_colors", + ] +} +``` + +### 4. Histogram Registration + +**File:** `extensions/browser/extension_function_histogram_value.h` + +```cpp +enum HistogramValue { + // ... + THEMECOLORS_GET = 1953, + ENUM_BOUNDARY +}; +``` + +**Purpose:** Tracks API usage in Chrome metrics + +--- + +## Usage Examples + +### Basic Color Retrieval + +```javascript +// Get all theme colors +const colors = await chrome.themeColors.get(); + +// Apply primary color to element +document.body.style.backgroundColor = colors.kColorSysPrimaryContainer; +document.body.style.color = colors.kColorSysOnPrimaryContainer; +``` + +### Theme-Aware UI Component + +```javascript +class ThemeAwareButton { + constructor() { + this.button = document.createElement('button'); + this.applyTheme(); + + // Listen for theme changes + chrome.themeColors.onChanged.addListener(() => { + this.applyTheme(); + }); + } + + async applyTheme() { + const colors = await chrome.themeColors.get(); + this.button.style.backgroundColor = colors.kColorButtonBackgroundProminent; + this.button.style.color = colors.kColorButtonForegroundProminent; + this.button.style.borderColor = colors.kColorSysTonalOutline; + } +} +``` + +### Light/Dark Mode Detection + +```javascript +async function getCurrentThemeMode() { + const colors = await chrome.themeColors.get(); + + // Compare surface lightness to determine mode + const surfaceColor = colors.kColorSysSurface; + const luminance = getRelativeLuminance(surfaceColor); + + return luminance > 0.5 ? 'light' : 'dark'; +} + +function getRelativeLuminance(hexColor) { + const rgb = parseInt(hexColor.slice(1), 16); + const r = ((rgb >> 16) & 0xff) / 255; + const g = ((rgb >> 8) & 0xff) / 255; + const b = (rgb & 0xff) / 255; + return 0.2126 * r + 0.7152 * g + 0.0722 * b; +} +``` + +### CSS Custom Properties Integration + +```javascript +async function applyThemeToCSSVariables() { + const colors = await chrome.themeColors.get(); + const root = document.documentElement; + + // Map theme colors to CSS variables + Object.entries(colors).forEach(([name, value]) => { + const cssVarName = `--${name.replace(/([A-Z])/g, '-$1').toLowerCase()}`; + root.style.setProperty(cssVarName, value); + }); +} + +// CSS Usage: +// background: var(--k-color-sys-primary); +// color: var(--k-color-sys-on-primary); +``` + +### Material Design 3 Color Scheme + +```javascript +async function createMaterialColorScheme() { + const colors = await chrome.themeColors.get(); + + return { + primary: colors.kColorSysPrimary, + primaryContainer: colors.kColorSysPrimaryContainer, + onPrimary: colors.kColorSysOnPrimary, + onPrimaryContainer: colors.kColorSysOnPrimaryContainer, + + secondary: colors.kColorSysSecondary, + secondaryContainer: colors.kColorSysSecondaryContainer, + onSecondary: colors.kColorSysOnSecondary, + onSecondaryContainer: colors.kColorSysOnSecondaryContainer, + + surface: colors.kColorSysSurface, + surfaceVariant: colors.kColorSysSurfaceVariant, + onSurface: colors.kColorSysOnSurface, + onSurfaceVariant: colors.kColorSysOnSurfaceVariant, + + error: colors.kColorSysError, + errorContainer: colors.kColorSysErrorContainer, + onError: colors.kColorSysOnError, + onErrorContainer: colors.kColorSysOnErrorContainer, + }; +} +``` + +--- + +## Build Configuration + +### BUILD.gn Dependencies + +**File:** `chrome/browser/extensions/api/theme_colors/BUILD.gn` + +```gni +source_set("theme_colors") { + sources = [ + "theme_colors_api.cc", + "theme_colors_api.h", + ] + + deps = [ + "//base", # Core utilities + "//chrome/browser/profiles:profile", # Profile access + "//chrome/browser/themes", # Theme service + "//chrome/browser/ui", # Browser UI + "//chrome/common/extensions/api", # Generated API + "//content/public/browser", # Browser context + "//extensions/browser", # Extension framework + "//extensions/common", # Extension utilities + "//skia", # Graphics library + "//ui/color", # Color system + "//ui/native_theme", # OS theme + ] +} +``` + +### Compilation + +The API is compiled as part of the standard Chromium build: + +```bash +# Build Chromium with the theme colors API +autoninja -C out/Default chrome +``` + +--- + +## Technical Specifications + +### Performance + +- **API Call Latency:** < 1ms (synchronous color lookups) +- **Memory Footprint:** ~4KB per color dictionary +- **Color Count:** 150+ colors per theme +- **Event Frequency:** onChanged fires on theme mode changes only + +### Browser Compatibility + +- **Minimum Chromium Version:** 144+ (or custom OpenBrowser builds) +- **Platform Support:** All platforms (Windows, macOS, Linux, ChromeOS) +- **Extension Types:** Regular extensions, platform apps, legacy packaged apps + +### Security Considerations + +- **Unprivileged API:** No permissions required +- **Read-Only:** Cannot modify theme colors +- **Sandboxed:** Runs in extension process +- **No User Data:** Only exposes visual theme information + +--- + +## Future Enhancements + +Potential improvements to consider: + +1. **Selective Color Retrieval:** + ```javascript + // Get only specific colors + chrome.themeColors.get(['kColorSysPrimary', 'kColorSysOnPrimary']) + ``` + +2. **Color Filters:** + ```javascript + // Get only system colors or reference colors + chrome.themeColors.get({ category: 'system' }) + ``` + +3. **Theme Metadata:** + ```javascript + // Get theme information + chrome.themeColors.getThemeInfo() + // Returns: { mode: 'dark', customTheme: false, ... } + ``` + +4. **Color Manipulation:** + ```javascript + // Get derived colors + chrome.themeColors.derive('kColorSysPrimary', { opacity: 0.5 }) + ``` + +--- + +## Troubleshooting + +### Common Issues + +**Error: "ColorProvider not available"** +- **Cause:** Browser window not ready when API is called +- **Solution:** Wait for window to fully load or check in background script + +```javascript +// Wait for window +chrome.windows.getCurrent(() => { + chrome.themeColors.get().then(colors => { + // Use colors + }); +}); +``` + +**Colors not updating on theme change** +- **Cause:** Not listening to onChanged event +- **Solution:** Add event listener + +```javascript +chrome.themeColors.onChanged.addListener((changeInfo) => { + updateTheme(changeInfo.colors); +}); +``` + +--- + +## References + +- **Material Design 3 Color System:** https://m3.material.io/styles/color +- **Chromium Color ID Definitions:** `ui/color/color_id.h` +- **Extension API Documentation:** `chrome/common/extensions/api/theme_colors.json` +- **ColorProvider Source:** `ui/color/color_provider.h` + +--- + +## License + +Copyright 2024 The Chromium Authors. Licensed under the BSD-3-Clause license. + +--- + +**Document Version:** 1.0 +**Last Updated:** January 2026 +**Maintained By:** OpenBrowser Team diff --git a/chromium/patches/branding/branding_and_theme.patch.backup b/chromium/patches/branding/branding-assets.patch similarity index 86% rename from chromium/patches/branding/branding_and_theme.patch.backup rename to chromium/patches/branding/branding-assets.patch index 09a4c31..f5b7d7e 100644 --- a/chromium/patches/branding/branding_and_theme.patch.backup +++ b/chromium/patches/branding/branding-assets.patch @@ -2590,83 +2590,6 @@ index 87032bcf74573..46e0a70ccd789 100644 Theme updated to uploaded image -diff --git a/chrome/app/theme/chromium/mac/app.icns b/chrome/app/theme/chromium/mac/app.icns -index 97072c8c1157d..2ec93f208bae4 100644 -Binary files a/chrome/app/theme/chromium/mac/app.icns and b/chrome/app/theme/chromium/mac/app.icns differ -diff --git a/chrome/app/theme/chromium/product_logo.svg b/chrome/app/theme/chromium/product_logo.svg -index 5e0b254b8dbaf..e10b921abd6b1 100644 ---- a/chrome/app/theme/chromium/product_logo.svg -+++ b/chrome/app/theme/chromium/product_logo.svg -@@ -1 +1,4 @@ -- -\ No newline at end of file -+ -+ -+ -+ -diff --git a/chrome/app/theme/chromium/product_logo_128.png b/chrome/app/theme/chromium/product_logo_128.png -index 9ce48f920e87c..c901d2e6081a6 100644 -Binary files a/chrome/app/theme/chromium/product_logo_128.png and b/chrome/app/theme/chromium/product_logo_128.png differ -diff --git a/chrome/app/theme/chromium/product_logo_16.png b/chrome/app/theme/chromium/product_logo_16.png -index ce9084c733b2c..c6a9634b7a797 100644 -Binary files a/chrome/app/theme/chromium/product_logo_16.png and b/chrome/app/theme/chromium/product_logo_16.png differ -diff --git a/chrome/app/theme/chromium/product_logo_22_mono.png b/chrome/app/theme/chromium/product_logo_22_mono.png -index b8874d44bcde3..d7259c33706a9 100644 -Binary files a/chrome/app/theme/chromium/product_logo_22_mono.png and b/chrome/app/theme/chromium/product_logo_22_mono.png differ -diff --git a/chrome/app/theme/chromium/product_logo_24.png b/chrome/app/theme/chromium/product_logo_24.png -index d883fde3daa7e..d0d6d6cbbecb4 100644 -Binary files a/chrome/app/theme/chromium/product_logo_24.png and b/chrome/app/theme/chromium/product_logo_24.png differ -diff --git a/chrome/app/theme/chromium/product_logo_256.png b/chrome/app/theme/chromium/product_logo_256.png -index 4899f69aaba5c..16a8fe006b718 100644 -Binary files a/chrome/app/theme/chromium/product_logo_256.png and b/chrome/app/theme/chromium/product_logo_256.png differ -diff --git a/chrome/app/theme/chromium/product_logo_48.png b/chrome/app/theme/chromium/product_logo_48.png -index 9ec8436cbf853..b9c78d0e08a37 100644 -Binary files a/chrome/app/theme/chromium/product_logo_48.png and b/chrome/app/theme/chromium/product_logo_48.png differ -diff --git a/chrome/app/theme/chromium/product_logo_64.png b/chrome/app/theme/chromium/product_logo_64.png -index 8bd239e39c653..d47e06130b0d7 100644 -Binary files a/chrome/app/theme/chromium/product_logo_64.png and b/chrome/app/theme/chromium/product_logo_64.png differ -diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_16.png b/chrome/app/theme/default_100_percent/chromium/product_logo_16.png -index 77ac0f31cb21d..c6a9634b7a797 100644 -Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_16.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_16.png differ -diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_32.png b/chrome/app/theme/default_100_percent/chromium/product_logo_32.png -index 175b2917c9ee5..bf888d0de92fe 100644 -Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_32.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_32.png differ -diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png -index addde0e37401b..b7fe29c00d79d 100644 -Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22.png differ -diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png -index 0cf6cfc1d5a1b..ae6a1238beb5d 100644 -Binary files a/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png and b/chrome/app/theme/default_100_percent/chromium/product_logo_name_22_white.png differ -diff --git a/chrome/app/theme/default_100_percent/common/favicon_ntp.png b/chrome/app/theme/default_100_percent/common/favicon_ntp.png -index 79291d8c90432..2ce13a8cadaf3 100644 -Binary files a/chrome/app/theme/default_100_percent/common/favicon_ntp.png and b/chrome/app/theme/default_100_percent/common/favicon_ntp.png differ -diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_16.png b/chrome/app/theme/default_200_percent/chromium/product_logo_16.png -index 2b5899e392fb8..c6a9634b7a797 100644 -Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_16.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_16.png differ -diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_32.png b/chrome/app/theme/default_200_percent/chromium/product_logo_32.png -index 886113df438c5..bf888d0de92fe 100644 -Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_32.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_32.png differ -diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png -index a611e83849a50..8e4c9f9ee9560 100644 -Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22.png differ -diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png -index 926247cb9f8af..87cd9fee473bd 100644 -Binary files a/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png and b/chrome/app/theme/default_200_percent/chromium/product_logo_name_22_white.png differ -diff --git a/chrome/app/theme/default_200_percent/common/favicon_ntp.png b/chrome/app/theme/default_200_percent/common/favicon_ntp.png -index 841d0a4d3eaaa..6286728c00000 100644 -Binary files a/chrome/app/theme/default_200_percent/common/favicon_ntp.png and b/chrome/app/theme/default_200_percent/common/favicon_ntp.png differ -diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd -index 87c3c8382e602..d38aa879d082b 100644 ---- a/chrome/app/theme/theme_resources.grd -+++ b/chrome/app/theme/theme_resources.grd -@@ -160,6 +160,7 @@ - - - -+ - - - diff --git a/chrome/browser/favicon/favicon_utils.cc b/chrome/browser/favicon/favicon_utils.cc index eff6b7ccc596b..774d653bdcc98 100644 --- a/chrome/browser/favicon/favicon_utils.cc @@ -2710,49 +2633,6 @@ index eff6b7ccc596b..774d653bdcc98 100644 : gfx::ImageSkiaOperations::CreateColorMask(source, SK_ColorWHITE); } -diff --git a/chrome/browser/resources/new_tab_page/app.css b/chrome/browser/resources/new_tab_page/app.css -index e478fea59f056..7f971831f25b6 100644 ---- a/chrome/browser/resources/new_tab_page/app.css -+++ b/chrome/browser/resources/new_tab_page/app.css -@@ -57,18 +57,18 @@ - */ - :host([realbox-can-show-secondary-side][realbox-had-secondary-side]), - :host([realbox-can-show-secondary-side]) { -- --ntp-search-box-width: 746px; -+ --ntp-search-box-width: 900px; - } - - @media (min-width: 560px) { - :host { -- --ntp-search-box-width: 449px; -+ --ntp-search-box-width: 600px; - } - } - - @media (min-width: 672px) { - :host { -- --ntp-search-box-width: 561px; -+ --ntp-search-box-width: 750px; - } - } - -diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts -index 167ae9b24c89f..b3e65a5d99076 100644 ---- a/chrome/browser/resources/new_tab_page/app.ts -+++ b/chrome/browser/resources/new_tab_page/app.ts -@@ -1160,10 +1160,8 @@ export class AppElement extends AppElementBase { - } - - protected computeShowBrowserPromo_(): boolean { -- return !this.modulesEnabled_ || -- (this.modulesLoadedStatus_ !== -- ModuleLoadStatus.MODULE_LOAD_IN_PROGRESS && -- !this.modulesShownToUser); -+ // Disabled: Don't show "Make OpenBrowser Yours" setup list -+ return false; - } - - protected recordBrowserPromoMetrics_() { diff --git a/chrome/browser/resources/new_tab_page/icons/BUILD.gn b/chrome/browser/resources/new_tab_page/icons/BUILD.gn index 3ebefc4d55512..a21d09c60109d 100644 --- a/chrome/browser/resources/new_tab_page/icons/BUILD.gn @@ -2914,123 +2794,6 @@ index 83221a8e6f90f..ea3bc8cf4b002 100644 + + + -diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc -index 8634cbb4dc17a..ef53ad2540d79 100644 ---- a/chrome/browser/themes/theme_service_factory.cc -+++ b/chrome/browser/themes/theme_service_factory.cc -@@ -139,6 +139,7 @@ void ThemeServiceFactory::RegisterProfilePrefs( - registry->RegisterIntegerPref( - prefs::kDeprecatedUserColorDoNotUse, SK_ColorTRANSPARENT, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); -+ // Use transparent to indicate no custom color (will use baseline grayscale) - registry->RegisterIntegerPref(prefs::kUserColor, SK_ColorTRANSPARENT); - registry->RegisterIntegerPref( - prefs::kDeprecatedBrowserColorVariantDoNotUse, -diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc -index 350f052b92aef..36dec424c89f2 100644 ---- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc -+++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc -@@ -407,7 +407,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, - {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) - : ui::ColorTransform(SK_ColorWHITE)}; - mixer[kColorSearchboxForeground] = -- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) - : ui::ColorTransform(SK_ColorBLACK)}; - mixer[kColorSearchboxPlaceholder] = - {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -@@ -440,7 +440,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, - {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) - : gfx::kGoogleBlue600}; - mixer[kColorSearchboxResultsForeground] = -- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) - : ui::ColorTransform(SK_ColorBLACK)}; - mixer[kColorSearchboxResultsForegroundDimmed] = - {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc -index 3544f1b569ee1..760b5a59e82df 100644 ---- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc -+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc -@@ -626,7 +626,7 @@ gfx::RoundedCornersF IconLabelBubbleView::GetCornerRadii() const { - if (radii_.has_value()) { - return radii_.value(); - } -- return gfx::RoundedCornersF(GetPreferredSize().height() / 2); -+ return gfx::RoundedCornersF(4); - } - - void IconLabelBubbleView::SetCornerRadii(const gfx::RoundedCornersF& radii) { -diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc -index 2dbe7d318cd7b..989abffe08143 100644 ---- a/chrome/browser/ui/views/location_bar/location_bar_view.cc -+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc -@@ -245,7 +245,7 @@ LocationBarView::LocationBarView(Browser* browser, - !v->GetOmniboxController()->IsPopupOpen(); - })); - views::FocusRing::Get(this)->SetOutsetFocusRingDisabled(true); -- views::InstallPillHighlightPathGenerator(this); -+ views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), 8); - - #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) - if (features::IsOsLevelGeolocationPermissionSupportEnabled()) { -diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc -index d5306a85b1e0c..40c9d0ffd3971 100644 ---- a/chrome/browser/ui/views/tabs/tab.cc -+++ b/chrome/browser/ui/views/tabs/tab.cc -@@ -372,8 +372,20 @@ void Tab::Layout(PassKey) { - - // The bounds for the favicon will include extra width for the attention - // indicator, but visually it will be smaller at kFaviconSize wide. -- gfx::Rect favicon_bounds(start, contents_rect.y(), 0, 0); -+ -+ gfx::Rect favicon_bounds; - if (showing_icon_) { -+ const gfx::Size icon_size = icon_->GetPreferredSize(); -+ const gfx::Insets icon_insets = icon_->GetInsets(); -+ -+ // Center the favicon vertically so its middle aligns with the content area -+ // middle. We need to add the inset back because Inset(-insets) will -+ // subtract it later. -+ const int content_middle_y = contents_rect.y() + contents_rect.height() / 2; -+ const int favicon_y = content_middle_y - icon_size.height() / 2 + icon_insets.top(); -+ -+ favicon_bounds = gfx::Rect(start, favicon_y, 0, 0); -+ - if (center_icon_) { - // When centering the favicon, the favicon is allowed to escape the normal - // contents rect. -@@ -389,7 +401,9 @@ void Tab::Layout(PassKey) { - - // Add space for insets outside the favicon bounds. - favicon_bounds.Inset(-icon_->GetInsets()); -- favicon_bounds.set_size(icon_->GetPreferredSize()); -+ favicon_bounds.set_size(icon_size); -+ } else { -+ favicon_bounds = gfx::Rect(start, contents_rect.y(), 0, 0); - } - icon_->SetBoundsRect(favicon_bounds); - icon_->SetVisible(showing_icon_); -diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc -index 832ca90c1538c..ce053294b3ad0 100644 ---- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc -+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc -@@ -616,13 +616,8 @@ void NewTabPageHandler::GetMostVisitedSettings( - } - - void NewTabPageHandler::GetDoodle(GetDoodleCallback callback) { -- search_provider_logos::LogoCallbacks callbacks; -- callbacks.on_cached_encoded_logo_available = -- base::BindOnce(&NewTabPageHandler::OnLogoAvailable, -- weak_ptr_factory_.GetWeakPtr(), std::move(callback)); -- // This will trigger re-downloading the doodle and caching it. This means a -- // new doodle will be returned on subsequent NTP loads. -- logo_service_->GetLogo(std::move(callbacks), /*for_webui_ntp=*/true); -+ // Disable Google doodle downloading - always return null to use local logo -+ std::move(callback).Run(nullptr); - } - - void NewTabPageHandler::UpdatePromoData() { diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index 12651b3c1e9b0..ff46a3238a763 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc @@ -3138,41 +2901,6 @@ index 5c35bda0d736b..2f3d804fbb80e 100644 +H_LINE_TO, 8, +CLOSE \ No newline at end of file -diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc -index 6d2ea1d68430b..406d9402d41e1 100644 ---- a/components/search/ntp_features.cc -+++ b/components/search/ntp_features.cc -@@ -98,7 +98,7 @@ BASE_FEATURE(kNtpDummyModules, base::FEATURE_DISABLED_BY_DEFAULT); - - // If enabled, Google Drive module will be shown. - // This is a kill switch. Keep indefinitely. --BASE_FEATURE(kNtpDriveModule, base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kNtpDriveModule, base::FEATURE_ENABLED_BY_DEFAULT); - - // If enabled, the NTP Drive module does not require sync. - BASE_FEATURE(kNtpDriveModuleHistorySyncRequirement, -@@ -121,7 +121,7 @@ BASE_FEATURE(kNtpMiddleSlotPromo, base::FEATURE_ENABLED_BY_DEFAULT); - - // If enabled, middle slot promo will be dismissed from New Tab Page until new - // promo message is populated --BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_DISABLED_BY_DEFAULT); -+BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_ENABLED_BY_DEFAULT); - - // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". - // This is used for an emergency Finch param. Keep indefinitely. -diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h -index d8c168edc6c92..2d8243d947b94 100644 ---- a/ui/native_theme/native_theme.h -+++ b/ui/native_theme/native_theme.h -@@ -602,7 +602,7 @@ class COMPONENT_EXPORT(NATIVE_THEME) NativeTheme { - std::optional user_color_; - std::optional scheme_variant_; - ColorProviderKey::UserColorSource preferred_color_source_ = -- ColorProviderKey::UserColorSource::kAccent; -+ ColorProviderKey::UserColorSource::kBaseline; - base::TimeDelta caret_blink_interval_; - - raw_ptr associated_web_instance_ = nullptr; diff --git a/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn b/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn index 8ad6296ea91dc..717abf4b71523 100644 --- a/ui/webui/resources/cr_components/searchbox/icons/BUILD.gn @@ -3186,493 +2914,3 @@ index 8ad6296ea91dc..717abf4b71523 100644 "mic.svg", ] input_files_base_dir = -diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.css b/ui/webui/resources/cr_components/searchbox/searchbox.css -index dc4fdb93e0fa3..5ca09ff564360 100644 ---- a/ui/webui/resources/cr_components/searchbox/searchbox.css -+++ b/ui/webui/resources/cr_components/searchbox/searchbox.css -@@ -12,7 +12,7 @@ - :host { - /* Embedders should define --cr-searchbox-min-width. */ - --cr-searchbox-width: var(--cr-searchbox-min-width); -- --cr-searchbox-border-radius: calc(0.5 * var(--cr-searchbox-height)); -+ --cr-searchbox-border-radius: 8px; - --cr-searchbox-icon-width: 26px; - --cr-searchbox-inner-icon-margin: 8px; - --cr-searchbox-voice-icon-offset: 16px; -@@ -274,11 +274,29 @@ cr-searchbox-icon { - } - - :host(:not([use-webkit-search-icons_])) #voiceSearchButton { -- background-image: url(//resources/cr_components/searchbox/icons/mic.svg); -+ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/mic.svg); -+ -webkit-mask-position: center; -+ -webkit-mask-repeat: no-repeat; -+ -webkit-mask-size: 21px 21px; - } - - :host(:not([use-webkit-search-icons_])) #lensSearchButton { -- background-image: url(//resources/cr_components/searchbox/icons/camera.svg); -+ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/camera.svg); -+ -webkit-mask-position: center; -+ -webkit-mask-repeat: no-repeat; -+ -webkit-mask-size: 21px 21px; -+} -+ -+/* White icons in dark mode */ -+:host(:not([use-webkit-search-icons_])[is-dark]) #voiceSearchButton, -+:host(:not([use-webkit-search-icons_])[is-dark]) #lensSearchButton { -+ background-color: white; -+} -+ -+/* Black icons in light mode */ -+:host(:not([use-webkit-search-icons_]):not([is-dark])) #voiceSearchButton, -+:host(:not([use-webkit-search-icons_]):not([is-dark])) #lensSearchButton { -+ background-color: black; - } - - :host([use-webkit-search-icons_]) #voiceSearchButton { -@@ -373,7 +391,7 @@ search-animated-glow { - } - - :host([ntp-realbox-next-enabled]) { -- --cr-searchbox-border-radius: 26px; -+ --cr-searchbox-border-radius: 8px; - --cr-searchbox-dropdown-padding-bottom: 12px; - /* Cannot touch this searchbox icon size var; - it's used by the rainbow outline AI button class in -@@ -540,7 +558,7 @@ search-animated-glow { - } - - :host([searchbox-layout-mode='Compact']) { -- --cr-searchbox-border-radius: 30px; -+ --cr-searchbox-border-radius: 8px; - --cr-searchbox-dropdown-padding-bottom: 10px; - --cr-searchbox-dropdown-padding-top: 10px; - --cr-searchbox-height: 56px; -diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_match.css b/ui/webui/resources/cr_components/searchbox/searchbox_match.css -index 514d780649bba..48fe44b9e8788 100644 ---- a/ui/webui/resources/cr_components/searchbox/searchbox_match.css -+++ b/ui/webui/resources/cr_components/searchbox/searchbox_match.css -@@ -221,13 +221,14 @@ - - .match { - font-weight: var(--cr-searchbox-match-font-weight, 600); -+ color: var(--color-searchbox-results-foreground); - } - - /* In the lens side panel searchbox, the typed prefix of the match should - * have a different color than the rest of the autocomplete suggestion. */ - :host(:not([is-top-chrome-searchbox_])) #contents span:not(.match), - #ellipsis { -- color: var(--color-searchbox-results-typed-prefix, --color-searchbox-results-foreground); -+ color: var(--color-searchbox-results-foreground); - } - - /* Used to override contents color in zero prefix matches */ -diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts -index 735615a4ba785..d95689b8b1196 100644 ---- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts -+++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts -@@ -15,7 +15,8 @@ export function getHtml(this: CrDrawerElement) { - - - -+ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, -+ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> - - - -+ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, -+ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> - RegisterWebSafeScheme(openbrowser::kOpenBrowserUIScheme); ++ ++ // Step 4: Register the OpenBrowser WebUI controller factory ++ content::WebUIControllerFactory::RegisterFactory( ++ OpenBrowserWebUIControllerFactory::GetInstance()); ++} +diff --git a/openbrowser/browser/openbrowser_browser_main_extra_parts.h b/openbrowser/browser/openbrowser_browser_main_extra_parts.h +new file mode 100644 +index 0000000000000..d77015a99b4b6 +--- /dev/null ++++ b/openbrowser/browser/openbrowser_browser_main_extra_parts.h +@@ -0,0 +1,22 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef OPENBROWSER_BROWSER_OPENBROWSER_BROWSER_MAIN_EXTRA_PARTS_H_ ++#define OPENBROWSER_BROWSER_OPENBROWSER_BROWSER_MAIN_EXTRA_PARTS_H_ ++ ++#include "chrome/browser/chrome_browser_main_extra_parts.h" ++ ++// Brave-style: handle OpenBrowser-specific browser initialization ++class OpenBrowserBrowserMainExtraParts : public ChromeBrowserMainExtraParts { ++ public: ++ OpenBrowserBrowserMainExtraParts(); ++ OpenBrowserBrowserMainExtraParts(const OpenBrowserBrowserMainExtraParts&) = delete; ++ OpenBrowserBrowserMainExtraParts& operator=(const OpenBrowserBrowserMainExtraParts&) = delete; ++ ~OpenBrowserBrowserMainExtraParts() override; ++ ++ // ChromeBrowserMainExtraParts overrides: ++ void PostBrowserStart() override; ++}; ++ ++#endif // OPENBROWSER_BROWSER_OPENBROWSER_BROWSER_MAIN_EXTRA_PARTS_H_ +diff --git a/openbrowser/browser/ui/webui/BUILD.gn b/openbrowser/browser/ui/webui/BUILD.gn +new file mode 100644 +index 0000000000000..2395dbbcf4054 +--- /dev/null ++++ b/openbrowser/browser/ui/webui/BUILD.gn +@@ -0,0 +1,21 @@ ++# Copyright 2024 The OpenBrowser Authors ++# Use of this source code is governed by a BSD-style license that can be ++# found in the LICENSE file. ++ ++source_set("webui") { ++ sources = [ ++ "openbrowser_web_ui_controller_factory.cc", ++ "openbrowser_web_ui_controller_factory.h", ++ ] ++ ++ deps = [ ++ "//base", ++ "//chrome/browser/profiles", ++ "//chrome/browser/ui/webui", ++ "//chrome/common", ++ "//content/public/browser", ++ "//content/public/common", ++ "//openbrowser/common", ++ "//url", ++ ] ++} +diff --git a/openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.cc b/openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.cc +new file mode 100644 +index 0000000000000..d82992fd9bf81 +--- /dev/null ++++ b/openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.cc +@@ -0,0 +1,77 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.h" ++ ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" ++#include "chrome/common/webui_url_constants.h" ++#include "content/public/browser/web_ui_controller.h" ++#include "content/public/common/url_constants.h" ++#include "openbrowser/common/openbrowser_constants.h" ++#include "url/gurl.h" ++ ++// static ++OpenBrowserWebUIControllerFactory* OpenBrowserWebUIControllerFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++OpenBrowserWebUIControllerFactory::OpenBrowserWebUIControllerFactory() = default; ++ ++OpenBrowserWebUIControllerFactory::~OpenBrowserWebUIControllerFactory() = default; ++ ++content::WebUI::TypeID OpenBrowserWebUIControllerFactory::GetWebUIType( ++ content::BrowserContext* browser_context, ++ const GURL& url) { ++ // Only handle openbrowser:// URLs ++ if (!url.SchemeIs(openbrowser::kOpenBrowserUIScheme)) { ++ return content::WebUI::kNoWebUI; ++ } ++ ++ // Brave-style: Convert openbrowser:// to chrome:// to check if it exists ++ // This is only for checking - the actual URL stays as openbrowser:// ++ GURL::Replacements replacements; ++ replacements.SetSchemeStr(content::kChromeUIScheme); ++ GURL chrome_url = url.ReplaceComponents(replacements); ++ ++ return ChromeWebUIControllerFactory::GetInstance()->GetWebUIType( ++ browser_context, chrome_url); ++} ++ ++bool OpenBrowserWebUIControllerFactory::UseWebUIForURL( ++ content::BrowserContext* browser_context, ++ const GURL& url) { ++ // Only handle openbrowser:// URLs ++ if (!url.SchemeIs(openbrowser::kOpenBrowserUIScheme)) { ++ return false; ++ } ++ ++ // Convert to chrome:// to check if it exists ++ GURL::Replacements replacements; ++ replacements.SetSchemeStr(content::kChromeUIScheme); ++ GURL chrome_url = url.ReplaceComponents(replacements); ++ ++ return ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL( ++ browser_context, chrome_url); ++} ++ ++std::unique_ptr ++OpenBrowserWebUIControllerFactory::CreateWebUIControllerForURL( ++ content::WebUI* web_ui, ++ const GURL& url) { ++ // Only handle openbrowser:// URLs ++ if (!url.SchemeIs(openbrowser::kOpenBrowserUIScheme)) { ++ return nullptr; ++ } ++ ++ // Brave-style: Convert openbrowser:// to chrome:// to create the controller ++ // The controller will use chrome:// internally, but the URL bar shows openbrowser:// ++ GURL::Replacements replacements; ++ replacements.SetSchemeStr(content::kChromeUIScheme); ++ GURL chrome_url = url.ReplaceComponents(replacements); ++ ++ return ChromeWebUIControllerFactory::GetInstance()->CreateWebUIControllerForURL( ++ web_ui, chrome_url); ++} +diff --git a/openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.h b/openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.h +new file mode 100644 +index 0000000000000..c315fac329fe3 +--- /dev/null ++++ b/openbrowser/browser/ui/webui/openbrowser_web_ui_controller_factory.h +@@ -0,0 +1,38 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef OPENBROWSER_BROWSER_UI_WEBUI_OPENBROWSER_WEB_UI_CONTROLLER_FACTORY_H_ ++#define OPENBROWSER_BROWSER_UI_WEBUI_OPENBROWSER_WEB_UI_CONTROLLER_FACTORY_H_ ++ ++#include ++ ++#include "base/no_destructor.h" ++#include "content/public/browser/web_ui_controller_factory.h" ++ ++// Brave-style: Factory that handles openbrowser:// URLs ++// Maps them to existing Chrome WebUI controllers ++class OpenBrowserWebUIControllerFactory : public content::WebUIControllerFactory { ++ public: ++ static OpenBrowserWebUIControllerFactory* GetInstance(); ++ ++ OpenBrowserWebUIControllerFactory(const OpenBrowserWebUIControllerFactory&) = delete; ++ OpenBrowserWebUIControllerFactory& operator=(const OpenBrowserWebUIControllerFactory&) = delete; ++ ++ // content::WebUIControllerFactory overrides: ++ content::WebUI::TypeID GetWebUIType(content::BrowserContext* browser_context, ++ const GURL& url) override; ++ bool UseWebUIForURL(content::BrowserContext* browser_context, ++ const GURL& url) override; ++ std::unique_ptr CreateWebUIControllerForURL( ++ content::WebUI* web_ui, ++ const GURL& url) override; ++ ++ private: ++ friend base::NoDestructor; ++ ++ OpenBrowserWebUIControllerFactory(); ++ ~OpenBrowserWebUIControllerFactory() override; ++}; ++ ++#endif // OPENBROWSER_BROWSER_UI_WEBUI_OPENBROWSER_WEB_UI_CONTROLLER_FACTORY_H_ +diff --git a/openbrowser/buildflags.gni b/openbrowser/buildflags.gni +new file mode 100644 +index 0000000000000..e0649261cd9ce +--- /dev/null ++++ b/openbrowser/buildflags.gni +@@ -0,0 +1,8 @@ ++# Copyright 2024 The OpenBrowser Authors ++# Use of this source code is governed by a BSD-style license that can be ++# found in the LICENSE file. ++ ++# OpenBrowser build flag - always true for OpenBrowser builds ++declare_args() { ++ openbrowser_build = true ++} +diff --git a/openbrowser/common/BUILD.gn b/openbrowser/common/BUILD.gn +new file mode 100644 +index 0000000000000..73cd0ff9b04fd +--- /dev/null ++++ b/openbrowser/common/BUILD.gn +@@ -0,0 +1,30 @@ ++# Copyright 2024 The OpenBrowser Authors ++# Use of this source code is governed by a BSD-style license that can be ++# found in the LICENSE file. ++ ++import("//build/buildflag_header.gni") ++import("//openbrowser/buildflags.gni") ++ ++buildflag_header("buildflags") { ++ header = "buildflags.h" ++ flags = [ "OPENBROWSER_BUILD=$openbrowser_build" ] ++} ++ ++source_set("common") { ++ sources = [ ++ "openbrowser_constants.cc", ++ "openbrowser_constants.h", ++ "openbrowser_url_rewrite.cc", ++ "openbrowser_url_rewrite.h", ++ ] ++ ++ public_deps = [ ++ ":buildflags", ++ ] ++ ++ deps = [ ++ "//base", ++ "//content/public/common", ++ "//url", ++ ] ++} +diff --git a/openbrowser/common/openbrowser_constants.cc b/openbrowser/common/openbrowser_constants.cc +new file mode 100644 +index 0000000000000..cae14f964717b +--- /dev/null ++++ b/openbrowser/common/openbrowser_constants.cc +@@ -0,0 +1,11 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "openbrowser/common/openbrowser_constants.h" ++ ++namespace openbrowser { ++ ++const char kOpenBrowserUIScheme[] = "openbrowser"; ++ ++} // namespace openbrowser +diff --git a/openbrowser/common/openbrowser_constants.h b/openbrowser/common/openbrowser_constants.h +new file mode 100644 +index 0000000000000..6c8cb3c7b039c +--- /dev/null ++++ b/openbrowser/common/openbrowser_constants.h +@@ -0,0 +1,15 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef OPENBROWSER_COMMON_OPENBROWSER_CONSTANTS_H_ ++#define OPENBROWSER_COMMON_OPENBROWSER_CONSTANTS_H_ ++ ++namespace openbrowser { ++ ++// URL scheme for OpenBrowser internal pages (like chrome://) ++extern const char kOpenBrowserUIScheme[]; ++ ++} // namespace openbrowser ++ ++#endif // OPENBROWSER_COMMON_OPENBROWSER_CONSTANTS_H_ +diff --git a/openbrowser/common/openbrowser_url_rewrite.cc b/openbrowser/common/openbrowser_url_rewrite.cc +new file mode 100644 +index 0000000000000..2262cd7c71550 +--- /dev/null ++++ b/openbrowser/common/openbrowser_url_rewrite.cc +@@ -0,0 +1,26 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "openbrowser/common/openbrowser_url_rewrite.h" ++ ++#include "content/public/common/url_constants.h" ++#include "openbrowser/common/openbrowser_constants.h" ++#include "url/gurl.h" ++ ++namespace openbrowser { ++ ++GURL GetDisplayURLForInternal(const GURL& url) { ++ // Only rewrite chrome:// URLs for UI display ++ // Never change the actual URL used for navigation ++ if (url.SchemeIs(content::kChromeUIScheme)) { ++ GURL::Replacements replacements; ++ replacements.SetSchemeStr(kOpenBrowserUIScheme); ++ return url.ReplaceComponents(replacements); ++ } ++ ++ // Return unchanged for all other URLs ++ return url; ++} ++ ++} // namespace openbrowser +diff --git a/openbrowser/common/openbrowser_url_rewrite.h b/openbrowser/common/openbrowser_url_rewrite.h +new file mode 100644 +index 0000000000000..f641d1173fb62 +--- /dev/null ++++ b/openbrowser/common/openbrowser_url_rewrite.h +@@ -0,0 +1,19 @@ ++// Copyright 2024 The OpenBrowser Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef OPENBROWSER_COMMON_OPENBROWSER_URL_REWRITE_H_ ++#define OPENBROWSER_COMMON_OPENBROWSER_URL_REWRITE_H_ ++ ++class GURL; ++ ++namespace openbrowser { ++ ++// Brave-style: Rewrites chrome:// URLs to openbrowser:// for display in UI ++// This does NOT change the actual URL used for navigation - only what the user sees ++// Example: chrome://settings → openbrowser://settings (for display only) ++GURL GetDisplayURLForInternal(const GURL& url); ++ ++} // namespace openbrowser ++ ++#endif // OPENBROWSER_COMMON_OPENBROWSER_URL_REWRITE_H_ diff --git a/chromium/patches/openbrowser_integration/openbrowser-assistant-integration.patch b/chromium/patches/openbrowser_integration/openbrowser-assistant-integration.patch new file mode 100644 index 0000000..4bbe208 --- /dev/null +++ b/chromium/patches/openbrowser_integration/openbrowser-assistant-integration.patch @@ -0,0 +1,644 @@ +diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd +index d38aa879d082b..3a86c54500ce1 100644 +--- a/chrome/app/theme/theme_resources.grd ++++ b/chrome/app/theme/theme_resources.grd +@@ -161,6 +161,7 @@ + + + ++ + + + +diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd +index a549f50a0d16a..af614822591c0 100644 +--- a/chrome/browser/browser_resources.grd ++++ b/chrome/browser/browser_resources.grd +@@ -229,6 +229,8 @@ + + + ++ ++ + + + +diff --git a/chrome/browser/extensions/component_extensions_allowlist/allowlist.cc b/chrome/browser/extensions/component_extensions_allowlist/allowlist.cc +index cd53ca53c51ff..bf68378f2d306 100644 +--- a/chrome/browser/extensions/component_extensions_allowlist/allowlist.cc ++++ b/chrome/browser/extensions/component_extensions_allowlist/allowlist.cc +@@ -34,6 +34,7 @@ bool IsComponentExtensionAllowlisted(const std::string& extension_id) { + constexpr auto kAllowed = base::MakeFixedFlatSet({ + extension_misc::kInAppPaymentsSupportAppId, + extension_misc::kPdfExtensionId, ++ extension_misc::kOpenBrowserAssistantExtensionId, + #if BUILDFLAG(IS_CHROMEOS) + extension_misc::kAssessmentAssistantExtensionId, + extension_misc::kAccessibilityCommonExtensionId, +diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc +index ba347da2a2d2e..076602a74ef9f 100644 +--- a/chrome/browser/extensions/component_loader.cc ++++ b/chrome/browser/extensions/component_loader.cc +@@ -505,6 +505,15 @@ void ComponentLoader::AddDefaultComponentExtensions( + DCHECK(!skip_session_components); + #endif // BUILDFLAG(IS_CHROMEOS) + ++#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) ++ // OpenBrowser Assistant - load from BINDATA resources ++ std::string openbrowser_manifest = ++ ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( ++ IDR_OPENBROWSER_ASSISTANT_MANIFEST); ++ base::FilePath extension_path(FILE_PATH_LITERAL("openbrowser_assistant")); ++ Add(openbrowser_manifest, extension_path); ++#endif ++ + if (!skip_session_components) { + AddWebStoreApp(); + #if BUILDFLAG(IS_CHROMEOS) +diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd +index c8f16f0451d7a..654a9a962f259 100644 +--- a/chrome/browser/resources/component_extension_resources.grd ++++ b/chrome/browser/resources/component_extension_resources.grd +@@ -22,6 +22,86 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.cc b/chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.cc +index d9315fa4fa5b0..c4ec7c1540ca3 100644 +--- a/chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.cc ++++ b/chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.cc +@@ -22,10 +22,13 @@ + #include "chrome/browser/ui/toolbar/toolbar_pref_names.h" + #include "chrome/browser/ui/ui_features.h" + #include "chrome/common/chrome_features.h" ++#include "chrome/common/extensions/extension_constants.h" + #include "chrome/common/pref_names.h" + #include "components/prefs/pref_change_registrar.h" + #include "components/prefs/pref_service.h" + #include "components/prefs/scoped_user_pref_update.h" ++#include "extensions/browser/extension_registry.h" ++#include "extensions/common/extension.h" + #include "ui/actions/action_id.h" + #include "ui/actions/actions.h" + +diff --git a/chrome/browser/ui/toolbar/toolbar_pref_names.cc b/chrome/browser/ui/toolbar/toolbar_pref_names.cc +index 2ac0c02e74ee0..47369cb48522e 100644 +--- a/chrome/browser/ui/toolbar/toolbar_pref_names.cc ++++ b/chrome/browser/ui/toolbar/toolbar_pref_names.cc +@@ -46,6 +46,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref( + prefs::kTabSearchMigrationComplete, false, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); ++ registry->RegisterBooleanPref(prefs::kPinnedOpenBrowserMigrationComplete, ++ false); + } + + } // namespace toolbar +diff --git a/chrome/browser/ui/toolbar/toolbar_pref_names.h b/chrome/browser/ui/toolbar/toolbar_pref_names.h +index c59d5f14f663d..05b27103a00ac 100644 +--- a/chrome/browser/ui/toolbar/toolbar_pref_names.h ++++ b/chrome/browser/ui/toolbar/toolbar_pref_names.h +@@ -33,6 +33,10 @@ inline constexpr char kPinnedCastMigrationComplete[] = + inline constexpr char kTabSearchMigrationComplete[] = + "toolbar.tab_search_migration_complete"; + ++// Indicates whether the OpenBrowser extension has been auto-pinned. ++inline constexpr char kPinnedOpenBrowserMigrationComplete[] = ++ "toolbar.pinned_openbrowser_migration_complete"; ++ + } // namespace prefs + + namespace toolbar { +diff --git a/chrome/browser/ui/views/frame/contents_rounded_corner.cc b/chrome/browser/ui/views/frame/contents_rounded_corner.cc +index 597e5905bc40d..231fa20f55d71 100644 +--- a/chrome/browser/ui/views/frame/contents_rounded_corner.cc ++++ b/chrome/browser/ui/views/frame/contents_rounded_corner.cc +@@ -36,16 +36,17 @@ gfx::Size ContentsRoundedCorner::CalculatePreferredSize( + // http://crbug.com/40178332). The nullptr dereference does not always + // crash due to compiler optimizations, so CHECKing here ensures we crash. + CHECK(GetLayoutProvider()); +- const float corner_radius = GetLayoutProvider()->GetCornerRadiusMetric( +- views::ShapeContextTokens::kContentSeparatorRadius); ++ // Remove rounded corners for new tab page - override to 0 ++ const float corner_radius = 0 * GetLayoutProvider()->GetCornerRadiusMetric( ++ corner_radius_token_); + const float corner_size = corner_radius + views::Separator::kThickness; + return gfx::Size(corner_size, corner_size); + } + + void ContentsRoundedCorner::OnBoundsChanged(const gfx::Rect& previous_bounds) { + SkPathBuilder path; +- const float corner_radius = +- GetLayoutProvider()->GetCornerRadiusMetric(corner_radius_token_); ++ // Remove rounded corners for new tab page ++ const float corner_radius = 0; + const gfx::Rect local_bounds = GetLocalBounds(); + if (is_right_aligned_callback_.Run()) { + path.moveTo(0, 0); +@@ -82,8 +83,8 @@ void ContentsRoundedCorner::OnPaint(gfx::Canvas* canvas) { + flags.setStyle(cc::PaintFlags::kStroke_Style); + flags.setAntiAlias(true); + +- const float corner_radius = +- GetLayoutProvider()->GetCornerRadiusMetric(corner_radius_token_); ++ // Remove rounded corners for new tab page ++ const float corner_radius = 0; + const gfx::Rect local_bounds = GetLocalBounds(); + SkPathBuilder path; + if (is_right_aligned_callback_.Run()) { +diff --git a/chrome/browser/ui/views/side_panel/side_panel.cc b/chrome/browser/ui/views/side_panel/side_panel.cc +index 8a128e29e68eb..d5740ceed44f0 100644 +--- a/chrome/browser/ui/views/side_panel/side_panel.cc ++++ b/chrome/browser/ui/views/side_panel/side_panel.cc +@@ -60,7 +60,7 @@ namespace { + // This thickness includes the solid-color background and the inner round-rect + // border-color stroke. It does not include the outer-color separator. + int GetBorderThickness() { +- return 8 + views::Separator::kThickness; ++ return 0; + } + + // This is how many units of the toolbar are essentially expected to be +@@ -125,9 +125,8 @@ class SidePanelBorder : public views::Border { + view.GetLocalBounds(), view.layer()->device_scale_factor()); + + gfx::RectF scaled_contents_bounds_f = scaled_view_bounds_f; +- const float corner_radius = +- dsf * view.GetLayoutProvider()->GetCornerRadiusMetric( +- views::ShapeContextTokens::kSidePanelContentRadius); ++ // Remove rounded corners for all sidepanels ++ const float corner_radius = 0; + const gfx::InsetsF insets_in_pixels( + gfx::ConvertInsetsToPixels(GetInsets(), dsf)); + scaled_contents_bounds_f.Inset(insets_in_pixels); +@@ -191,7 +190,7 @@ class SidePanelBorder : public views::Border { + // there is a header we want to increase the top inset to give room for the + // header to paint on top of the border area. + int top_inset = +- views::Separator::kThickness + header_height_ - GetBorderInsets().top(); ++ views::Separator::kThickness + header_height_ - GetBorderInsets().top() + 1; + return GetBorderInsets() + gfx::Insets::TLBR(top_inset, 0, 0, 0); + } + gfx::Size GetMinimumSize() const override { +@@ -246,11 +245,8 @@ class ContentParentView : public views::View { + } + + gfx::RoundedCornersF GetRoundedCorners() { +- return should_round_corners_ && GetLayoutProvider() +- ? gfx::RoundedCornersF( +- GetLayoutProvider()->GetCornerRadiusMetric( +- views::ShapeContextTokens::kSidePanelContentRadius)) +- : gfx::RoundedCornersF(); ++ // Remove rounded corners for all sidepanels ++ return gfx::RoundedCornersF(0); + } + + bool should_round_corners_ = false; +diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc +index c79799b24b682..2bca27c33d5f3 100644 +--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc ++++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc +@@ -130,6 +130,17 @@ void SidePanelCoordinator::Show( + + SidePanelEntry* entry = GetEntryForUniqueKey(input); + ++ // Close OpenBrowser Assistant when any other content sidepanel is opening ++ if (entry->type() == SidePanelEntry::PanelType::kContent && ++ input.key.id() != SidePanelEntryId::kOpenBrowserAssistant && ++ IsSidePanelShowing(SidePanelEntry::PanelType::kContent) && ++ GetCurrentEntryId(SidePanelEntry::PanelType::kContent) == ++ SidePanelEntryId::kOpenBrowserAssistant) { ++ Close(SidePanelEntry::PanelType::kContent, ++ SidePanelEntryHideReason::kSidePanelClosed, ++ /*suppress_animations=*/true); ++ } ++ + if (!IsSidePanelShowing(entry->type())) { + SetOpenedTimestamp(entry->type(), base::TimeTicks::Now()); + SidePanelUtil::RecordSidePanelOpen(entry->type(), open_trigger); +diff --git a/chrome/browser/ui/views/side_panel/side_panel_entry_id.h b/chrome/browser/ui/views/side_panel/side_panel_entry_id.h +index 201d94283a5c0..0a389c4429d65 100644 +--- a/chrome/browser/ui/views/side_panel/side_panel_entry_id.h ++++ b/chrome/browser/ui/views/side_panel/side_panel_entry_id.h +@@ -40,6 +40,7 @@ + V(kMerchantTrust, kActionSidePanelShowMerchantTrust, "MerchantTrust") \ + V(kComments, kActionSidePanelShowComments, "Comments") \ + V(kGlic, kActionSidePanelShowGlic, "Glic") \ ++ V(kOpenBrowserAssistant, std::nullopt, "OpenBrowserAssistant") \ + /* Extensions (nothing more should be added below here) */ \ + V(kExtension, std::nullopt, "Extension") + +diff --git a/chrome/browser/ui/views/side_panel/side_panel_header_controller.cc b/chrome/browser/ui/views/side_panel/side_panel_header_controller.cc +index 3086e688c3cfe..1095d76a934d0 100644 +--- a/chrome/browser/ui/views/side_panel/side_panel_header_controller.cc ++++ b/chrome/browser/ui/views/side_panel/side_panel_header_controller.cc +@@ -82,9 +82,12 @@ SidePanelHeaderController::SidePanelHeaderController( + CHECK(side_panel_entry_); + actions::ActionItem* const action_item = + SidePanelUtil::GetActionItem(browser, side_panel_entry->key()); +- action_item_controller_subscription_ = action_item->AddActionChangedCallback( +- base::BindRepeating(&SidePanelHeaderController::OnActionItemChanged, +- base::Unretained(this))); ++ // Some entries like OpenBrowserAssistant don't have ActionItems ++ if (action_item) { ++ action_item_controller_subscription_ = action_item->AddActionChangedCallback( ++ base::BindRepeating(&SidePanelHeaderController::OnActionItemChanged, ++ base::Unretained(this))); ++ } + side_panel_toolbar_pinning_controller_observation_.Observe( + side_panel_toolbar_pinning_controller); + } +@@ -267,9 +270,10 @@ void SidePanelHeaderController::UpdatePinButton() { + side_panel_toolbar_pinning_controller_->GetPinnedStateFor( + side_panel_entry_->key()); + pin_button_->SetToggled(current_pinned_state); ++ // Some entries like OpenBrowserAssistant don't have ActionItems + pin_button_->SetVisible( + !profile->IsIncognitoProfile() && !profile->IsGuestSession() && +- action_item->GetProperty(actions::kActionItemPinnableKey) == ++ action_item && action_item->GetProperty(actions::kActionItemPinnableKey) == + static_cast(actions::ActionPinnableState::kPinnable)); + + if (!current_pinned_state) { +@@ -280,9 +284,13 @@ void SidePanelHeaderController::UpdatePinButton() { + + ui::ImageModel SidePanelHeaderController::GetIconImage() { + CHECK(side_panel_entry_); +- ui::ImageModel icon = +- SidePanelUtil::GetActionItem(browser_, side_panel_entry_->key()) +- ->GetImage(); ++ actions::ActionItem* const action_item = ++ SidePanelUtil::GetActionItem(browser_, side_panel_entry_->key()); ++ // Some entries like OpenBrowserAssistant don't have ActionItems ++ if (!action_item) { ++ return ui::ImageModel(); ++ } ++ ui::ImageModel icon = action_item->GetImage(); + if (icon.IsVectorIcon()) { + icon = ui::ImageModel::FromVectorIcon(*icon.GetVectorIcon().vector_icon(), + kColorSidePanelEntryIcon, +@@ -293,10 +301,13 @@ ui::ImageModel SidePanelHeaderController::GetIconImage() { + + std::u16string_view SidePanelHeaderController::GetTitleText() { + CHECK(side_panel_entry_); +- return side_panel_entry_->GetProperty(kShouldShowTitleInSidePanelHeaderKey) +- ? SidePanelUtil::GetActionItem(browser_, side_panel_entry_->key()) +- ->GetText() +- : std::u16string_view(); ++ if (!side_panel_entry_->GetProperty(kShouldShowTitleInSidePanelHeaderKey)) { ++ return std::u16string_view(); ++ } ++ actions::ActionItem* const action_item = ++ SidePanelUtil::GetActionItem(browser_, side_panel_entry_->key()); ++ // Some entries like OpenBrowserAssistant don't have ActionItems ++ return action_item ? action_item->GetText() : std::u16string_view(); + } + + void SidePanelHeaderController::UpdatePinState() { +diff --git a/chrome/browser/ui/views/side_panel/side_panel_toolbar_pinning_controller.cc b/chrome/browser/ui/views/side_panel/side_panel_toolbar_pinning_controller.cc +index f38005a7f2f93..ddb42374bb83b 100644 +--- a/chrome/browser/ui/views/side_panel/side_panel_toolbar_pinning_controller.cc ++++ b/chrome/browser/ui/views/side_panel/side_panel_toolbar_pinning_controller.cc +@@ -66,7 +66,10 @@ bool SidePanelToolbarPinningController::GetPinnedStateFor( + + std::optional action_id = + SidePanelEntryIdToActionId(key.id()); +- CHECK(action_id.has_value()); ++ // Some entries like OpenBrowserAssistant don't have ActionIds ++ if (!action_id.has_value()) { ++ return false; ++ } + return actions_model->Contains(action_id.value()); + } + } +@@ -75,9 +78,13 @@ void SidePanelToolbarPinningController::UpdatePinState( + SidePanelEntry::Key entry_key) { + Profile* const profile = browser_view_->GetProfile(); + +- std::optional action_id = +- SidePanelUtil::GetActionItem(browser_view_->browser(), entry_key) +- ->GetActionId(); ++ actions::ActionItem* const action_item = ++ SidePanelUtil::GetActionItem(browser_view_->browser(), entry_key); ++ // Some entries like OpenBrowserAssistant don't have ActionItems ++ if (!action_item) { ++ return; ++ } ++ std::optional action_id = action_item->GetActionId(); + CHECK(action_id.has_value()); + + bool updated_pin_state = false; +@@ -118,7 +125,10 @@ void SidePanelToolbarPinningController::UpdateActiveState( + } else { + std::optional action_id = + SidePanelEntryIdToActionId(key.id()); +- CHECK(action_id.has_value()); ++ // Some entries like OpenBrowserAssistant don't have ActionIds ++ if (!action_id.has_value()) { ++ return; ++ } + toolbar_container->UpdateActionState(*action_id, show_active_in_toolbar); + } + } +diff --git a/chrome/browser/ui/views/side_panel/side_panel_util.cc b/chrome/browser/ui/views/side_panel/side_panel_util.cc +index 2dbc320b01891..a24771df3ddba 100644 +--- a/chrome/browser/ui/views/side_panel/side_panel_util.cc ++++ b/chrome/browser/ui/views/side_panel/side_panel_util.cc +@@ -9,6 +9,7 @@ + #include "base/metrics/user_metrics_action.h" + #include "base/strings/strcat.h" + #include "base/time/time.h" ++#include "url/gurl.h" + #include "chrome/browser/history_clusters/history_clusters_service_factory.h" + #include "chrome/browser/profiles/profile.h" + #include "chrome/browser/ui/browser.h" +@@ -23,6 +24,8 @@ + #include "chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.h" + #include "chrome/browser/ui/views/side_panel/side_panel_content_proxy.h" + #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" ++#include "chrome/browser/ui/views/side_panel/side_panel_entry.h" ++#include "chrome/browser/ui/views/side_panel/side_panel_entry_scope.h" + #include "chrome/browser/ui/views/side_panel/side_panel_registry.h" + #include "chrome/browser/ui/views/side_panel/side_panel_ui.h" + #include "chrome/browser/ui/webui_browser/webui_browser.h" +@@ -30,8 +33,11 @@ + #include "components/history_clusters/core/features.h" + #include "components/history_clusters/core/history_clusters_service.h" + #include "components/prefs/pref_service.h" ++#include "extensions/browser/extension_registry.h" ++#include "extensions/common/constants.h" + #include "ui/accessibility/accessibility_features.h" + #include "ui/actions/actions.h" ++#include "ui/views/controls/webview/webview.h" + + #if BUILDFLAG(ENABLE_GLIC) + #include "chrome/browser/glic/public/glic_enabling.h" +@@ -96,6 +102,23 @@ void SidePanelUtil::PopulateGlobalEntries(Browser* browser, + ->CreateAndRegisterEntry(browser, window_registry); + } + #endif ++ ++ // OpenBrowser Assistant - register side panel entry ++ auto assistant_entry = std::make_unique( ++ SidePanelEntry::Key(SidePanelEntry::Id::kOpenBrowserAssistant), ++ base::BindRepeating( ++ [](Profile* profile, SidePanelEntryScope& scope) ++ -> std::unique_ptr { ++ auto web_view = std::make_unique(profile); ++ web_view->LoadInitialURL(GURL( ++ "chrome-extension://cbjnlnglpbmhbeekoalifpaallpcmelp/sidebar.html")); ++ return web_view; ++ }, ++ browser->profile()), ++ base::BindRepeating([]() { return 360; })); ++ // Hide the header (which includes the close button) for the assistant ++ assistant_entry->set_should_show_header(false); ++ window_registry->Register(std::move(assistant_entry)); + } + + SidePanelContentProxy* SidePanelUtil::GetSidePanelContentProxy( +@@ -123,6 +146,11 @@ actions::ActionItem* SidePanelUtil::GetActionItem( + return action_item; + } + ++ // OpenBrowserAssistant doesn't use ActionItems ++ if (entry_key.id() == SidePanelEntryId::kOpenBrowserAssistant) { ++ return nullptr; ++ } ++ + std::optional action_id = + SidePanelEntryIdToActionId(entry_key.id()); + CHECK(action_id.has_value()); +diff --git a/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.cc b/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.cc +index 4ef3578829404..a1d02e1c3dc4b 100644 +--- a/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.cc ++++ b/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.cc +@@ -308,6 +308,21 @@ void PinnedActionToolbarButton::OnAnchorCountChanged(size_t anchor_count) { + } + } + ++bool PinnedActionToolbarButton::CanUserUnpin() const { ++ // Get action ID ++ const actions::ActionId& action_id = action_id_; ++ const std::optional& id_str = ++ actions::ActionIdMap::ActionIdToString(action_id); ++ ++ // Prevent unpinning OpenBrowser ++ if (id_str.has_value() && ++ id_str->find("openbrowser") != std::string::npos) { ++ return false; ++ } ++ ++ return !permanent_; // existing logic ++} ++ + std::unique_ptr + PinnedActionToolbarButton::GetActionViewInterface() { + return std::make_unique(this); +diff --git a/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h b/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h +index 5faebc2c5021d..7352e6df452ae 100644 +--- a/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h ++++ b/chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h +@@ -56,6 +56,7 @@ class PinnedActionToolbarButton : public ToolbarButton { + bool IsIconVisible() { return is_icon_visible_; } + bool IsPinned() { return pinned_; } + bool IsPermanent() { return permanent_; } ++ bool CanUserUnpin() const; + views::View* GetImageContainerView() { return image_container_view(); } + + bool ShouldSkipExecutionForTesting() { return skip_execution_; } +diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc +index e86eec19bd872..b2166b6249940 100644 +--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc ++++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc +@@ -71,6 +71,9 @@ + #include "chrome/browser/ui/views/performance_controls/battery_saver_button.h" + #include "chrome/browser/ui/views/performance_controls/performance_intervention_button.h" + #include "chrome/browser/ui/views/side_panel/side_panel.h" ++#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" ++#include "chrome/browser/ui/views/side_panel/side_panel_entry.h" ++#include "chrome/browser/ui/views/side_panel/side_panel_entry_id.h" + #include "chrome/browser/ui/views/tabs/tab_strip.h" + #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" + #include "chrome/browser/ui/views/toolbar/app_menu.h" +@@ -115,6 +118,7 @@ + #include "ui/base/window_open_disposition_utils.h" + #include "ui/color/color_id.h" + #include "ui/color/color_provider.h" ++#include "ui/gfx/color_utils.h" + #include "ui/compositor/layer.h" + #include "ui/gfx/canvas.h" + #include "ui/gfx/image/canvas_image_source.h" +@@ -522,6 +526,17 @@ void ToolbarView::Init() { + container_view_->AddChildView(std::make_unique()); + overflow_button_->SetVisible(false); + ++ // OpenBrowser Assistant button ++ auto assistant_button = std::make_unique( ++ base::BindRepeating(&ToolbarView::OnAssistantButtonPressed, ++ base::Unretained(this))); ++ assistant_button->SetTooltipText(u"Open Assistant"); ++ assistant_button->GetViewAccessibility().SetName(u"Assistant"); ++ assistant_button->SetImageModel( ++ views::Button::STATE_NORMAL, ++ ui::ImageModel::FromResourceId(IDR_PRODUCT_LOGO_16)); ++ assistant_button_ = container_view_->AddChildView(std::move(assistant_button)); ++ + auto app_menu_button = std::make_unique(this); + app_menu_button->SetFlipCanvasOnPaintForRTLUI(true); + app_menu_button->GetViewAccessibility().SetName( +@@ -895,6 +910,16 @@ void ToolbarView::OnThemeChanged() { + LoadImages(); + } + ++ // Update OpenBrowser Assistant icon based on theme ++ if (assistant_button_) { ++ const bool is_dark_mode = ++ color_utils::IsDark(GetColorProvider()->GetColor(kColorToolbar)); ++ const int icon_id = is_dark_mode ? IDR_PRODUCT_LOGO_16_WHITE : IDR_PRODUCT_LOGO_16; ++ assistant_button_->SetImageModel( ++ views::Button::STATE_NORMAL, ++ ui::ImageModel::FromResourceId(icon_id)); ++ } ++ + SchedulePaint(); + } + +@@ -937,6 +962,19 @@ void ToolbarView::NewTabButtonPressed(const ui::Event& event) { + NewTabTypes::kNewTabButtonInToolbarForTouch); + } + ++void ToolbarView::OnAssistantButtonPressed() { ++ auto* side_panel_ui = browser_->GetFeatures().side_panel_ui(); ++ ++ // Toggle: if already showing OpenBrowser Assistant, close it; otherwise open it ++ if (side_panel_ui->IsSidePanelShowing(SidePanelEntry::PanelType::kContent) && ++ side_panel_ui->GetCurrentEntryId(SidePanelEntry::PanelType::kContent) == ++ SidePanelEntryId::kOpenBrowserAssistant) { ++ side_panel_ui->Close(SidePanelEntry::PanelType::kContent); ++ } else { ++ side_panel_ui->Show(SidePanelEntryId::kOpenBrowserAssistant); ++ } ++} ++ + bool ToolbarView::AcceleratorPressed(const ui::Accelerator& accelerator) { + const views::View* focused_view = focus_manager()->GetFocusedView(); + if (focused_view && (focused_view->GetID() == VIEW_ID_OMNIBOX)) { +diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h +index d29a28f80fb0c..57872d3be618d 100644 +--- a/chrome/browser/ui/views/toolbar/toolbar_view.h ++++ b/chrome/browser/ui/views/toolbar/toolbar_view.h +@@ -280,6 +280,8 @@ class ToolbarView : public views::AccessiblePaneView, + + void NewTabButtonPressed(const ui::Event& event); + ++ void OnAssistantButtonPressed(); ++ + void UpdateRecedingCornerRadius(); + + gfx::SlideAnimation size_animation_{this}; +@@ -308,6 +310,7 @@ class ToolbarView : public views::AccessiblePaneView, + raw_ptr app_menu_button_ = nullptr; + raw_ptr new_tab_button_ = nullptr; + raw_ptr tab_search_button_ = nullptr; ++ raw_ptr assistant_button_ = nullptr; + + const raw_ptr browser_; + const raw_ptr browser_view_; +diff --git a/extensions/common/constants.h b/extensions/common/constants.h +index a5b9d8e23035d..862265c403126 100644 +--- a/extensions/common/constants.h ++++ b/extensions/common/constants.h +@@ -284,6 +284,9 @@ inline constexpr char kChromeVoxExtensionId[] = + // The extension id of the PDF extension. + inline constexpr char kPdfExtensionId[] = "mhjfbmdgcfjbbpaeojofohoefgiehjai"; + ++// The extension id of the OpenBrowser Assistant extension. ++inline constexpr char kOpenBrowserAssistantExtensionId[] = "cbjnlnglpbmhbeekoalifpaallpcmelp"; ++ + #if BUILDFLAG(IS_CHROMEOS) + // The extension id of the Office Viewer component extension. + inline constexpr char kQuickOfficeComponentExtensionId[] = diff --git a/chromium/patches/theme/theme-color-system.patch b/chromium/patches/theme/theme-color-system.patch new file mode 100644 index 0000000..1a91b5a --- /dev/null +++ b/chromium/patches/theme/theme-color-system.patch @@ -0,0 +1,554 @@ +diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h +index 59296a7cb076a..c349c59837fe9 100644 +--- a/chrome/browser/ui/color/chrome_color_id.h ++++ b/chrome/browser/ui/color/chrome_color_id.h +@@ -657,6 +657,7 @@ + E_CPONLY(kColorSearchboxResultsForeground) \ + E_CPONLY(kColorSearchboxResultsForegroundDimmed) \ + E_CPONLY(kColorSearchboxResultsIcon) \ ++ E_CPONLY(kColorSearchboxResultsIconContainerBackground) \ + E_CPONLY(kColorSearchboxResultsIconFocusedOutline) \ + E_CPONLY(kColorSearchboxResultsIconSelected) \ + E_CPONLY(kColorSearchboxResultsUrl) \ +diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc +index d6f02fceb7ee8..9446c65b4d2cf 100644 +--- a/chrome/browser/ui/color/chrome_color_mixer.cc ++++ b/chrome/browser/ui/color/chrome_color_mixer.cc +@@ -192,9 +192,9 @@ void AddChromeColorMixer(ui::ColorProvider* provider, + mixer[kColorExtensionsMenuContainerBackground] = {ui::kColorSysSurface3}; + mixer[kColorFeatureFirstRunInfoContainerBackground] = {ui::kColorSysSurface3}; + mixer[kColorFeatureFirstRunIconColor] = {ui::kColorSysOnSurfaceSubtle}; +- mixer[kColorFeaturePromoBubbleBackground] = {gfx::kGoogleBlue700}; ++ mixer[kColorFeaturePromoBubbleBackground] = {dark_mode ? SK_ColorWHITE : SK_ColorBLACK}; + mixer[kColorFeaturePromoBubbleButtonBorder] = {gfx::kGoogleGrey300}; +- mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {gfx::kGoogleBlue300}; ++ mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {dark_mode ? SK_ColorBLACK : SK_ColorWHITE}; + mixer[kColorFeaturePromoBubbleDefaultButtonBackground] = { + kColorFeaturePromoBubbleForeground}; + mixer[kColorFeaturePromoBubbleDefaultButtonForeground] = { +diff --git a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc +index b2b1a40d80524..18cf4a075b8f2 100644 +--- a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc +@@ -53,7 +53,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + ui::kColorSysStateHoverOnSubtle}; + mixer[kColorNewTabPageButtonForeground] = {ui::kColorSysOnTonalContainer}; + +- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; ++ mixer[kColorComposeboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; + mixer[kColorComposeboxFont] = { + dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) +@@ -103,8 +105,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + : SkColorSetRGB(0xAD, 0xAF, 0xB8)}; + mixer[kColorComposeboxFileChipBackground] = {kColorSysSurface3_Light}; + mixer[kColorComposeboxFileChipFaviconBackground] = {kColorSysSurface_Light}; +- mixer[kColorComposeboxFileChipText] = { +- SkColorSetRGB(0x1F, 0x1F, 0x1F)}; ++ mixer[kColorComposeboxFileChipText] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : SkColorSetRGB(0x1F, 0x1F, 0x1F)}; + mixer[kColorComposeboxPdfChipIcon] = { + dark_mode ? SkColorSetRGB(0xAD, 0xAF, 0xB8) + : SkColorSetRGB(0x56, 0x59, 0x5E)}; +@@ -219,12 +222,20 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + ui::kColorSysOnPrimary}; + if (base::FeatureList::IsEnabled(ntp_features::kRealboxCr23Theming)) { + // Steady state theme colors. +- mixer[kColorSearchboxBackground] = {kColorToolbarBackgroundSubtleEmphasis}; ++ mixer[kColorSearchboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(kColorToolbarBackgroundSubtleEmphasis)}; ++ mixer[kColorSearchboxPlaceholder] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxTextDimmed)}; ++ mixer[kColorSearchboxSearchIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxLensVoiceIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(ui::kColorSysPrimary)}; + mixer[kColorSearchboxBackgroundHovered] = { + kColorToolbarBackgroundSubtleEmphasisHovered}; +- mixer[kColorSearchboxPlaceholder] = {kColorOmniboxTextDimmed}; +- mixer[kColorSearchboxSearchIconBackground] = {kColorOmniboxResultsIcon}; +- mixer[kColorSearchboxLensVoiceIconBackground] = {ui::kColorSysPrimary}; + mixer[kColorSearchboxSelectionBackground] = { + kColorOmniboxSelectionBackground}; + mixer[kColorSearchboxSelectionForeground] = { +@@ -235,42 +246,56 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, + kColorOmniboxAnswerIconGM3Background}; + mixer[kColorSearchboxAnswerIconForeground] = { + kColorOmniboxAnswerIconGM3Foreground}; +- mixer[kColorSearchboxForeground] = {kColorOmniboxText}; + mixer[kColorSearchboxResultsActionChip] = {ui::kColorSysTonalOutline}; + mixer[kColorSearchboxResultsActionChipIcon] = {ui::kColorSysPrimary}; + mixer[kColorSearchboxResultsActionChipFocusOutline] = { + ui::kColorSysStateFocusRing}; +- mixer[kColorSearchboxResultsBackgroundHovered] = { +- kColorOmniboxResultsBackgroundHovered}; +- mixer[kColorSearchboxResultsButtonHover] = { +- kColorOmniboxResultsButtonInkDropRowHovered}; +- mixer[kColorSearchboxResultsDimSelected] = { +- kColorOmniboxResultsTextDimmedSelected}; + mixer[kColorSearchboxResultsFocusIndicator] = { + kColorOmniboxResultsFocusIndicator}; +- mixer[kColorSearchboxResultsForeground] = {kColorOmniboxText}; +- mixer[kColorSearchboxResultsForegroundDimmed] = {kColorOmniboxTextDimmed}; +- mixer[kColorSearchboxResultsIcon] = {kColorOmniboxResultsIcon}; +- mixer[kColorSearchboxResultsIconSelected] = {kColorOmniboxResultsIcon}; + mixer[kColorSearchboxResultsIconFocusedOutline] = { + kColorOmniboxResultsButtonIconSelected}; +- mixer[kColorSearchboxResultsUrl] = {kColorOmniboxResultsUrl}; +- mixer[kColorSearchboxResultsUrlSelected] = { +- kColorOmniboxResultsUrlSelected}; ++ ++ mixer[kColorSearchboxForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(kColorOmniboxText)}; ++ mixer[kColorSearchboxResultsBackgroundHovered] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsBackgroundHovered)}; ++ mixer[kColorSearchboxResultsButtonHover] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsButtonInkDropRowHovered)}; ++ mixer[kColorSearchboxResultsDimSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsTextDimmedSelected)}; ++ mixer[kColorSearchboxResultsForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(kColorOmniboxText)}; ++ mixer[kColorSearchboxResultsForegroundDimmed] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxTextDimmed)}; ++ mixer[kColorSearchboxResultsIcon] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxResultsIconContainerBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxResultsIconSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : ui::ColorTransform(kColorOmniboxResultsIcon)}; ++ mixer[kColorSearchboxResultsUrl] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : ui::ColorTransform(kColorOmniboxResultsUrl)}; ++ mixer[kColorSearchboxResultsUrlSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : ui::ColorTransform(kColorOmniboxResultsUrlSelected)}; + mixer[kColorSearchboxShadow] = + ui::SetAlpha(gfx::kGoogleGrey900, + (dark_mode ? /* % opacity */ 0.32 : 0.1) * SK_AlphaOPAQUE); + +- // This determines weather the realbox expanded state background in dark +- // mode will match the omnibox or not. +- if (dark_mode && +- !ntp_features::kNtpRealboxCr23ExpandedStateBgMatchesOmnibox.Get()) { +- mixer[kColorSearchboxResultsBackground] = { +- kColorToolbarBackgroundSubtleEmphasis}; +- } else { +- mixer[kColorSearchboxResultsBackground] = { +- kColorOmniboxResultsBackground}; +- } ++ // Use base container color for searchbox results background in dark mode, omnibox color in light mode ++ mixer[kColorSearchboxResultsBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(kColorOmniboxResultsBackground)}; + } + + /* NewTabFooter */ +diff --git a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc +index 8d99d0d5e526e..0a06f2f6d7a0d 100644 +--- a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc ++++ b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc +@@ -27,8 +27,9 @@ void AddMaterialTabStripColorMixer(ui::ColorProvider* provider, + + // TODO(crbug.com/40883407): Validate final mappings for ChromeRefresh23 + // color. ++ const bool dark_mode = key.color_mode == ui::ColorProviderKey::ColorMode::kDark; + ui::ColorMixer& mixer = provider->AddMixer(); +- mixer[kColorTabBackgroundActiveFrameActive] = {ui::kColorSysBase}; ++ mixer[kColorTabBackgroundActiveFrameActive] = {dark_mode ? ui::kColorSysBaseContainer : ui::kColorSysSurface}; + mixer[kColorTabBackgroundActiveFrameInactive] = { + kColorTabBackgroundActiveFrameActive}; + +diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +index 558cc275c8847..350f052b92aef 100644 +--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +@@ -314,7 +314,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + ui::SelectBasedOnDarkInput(kColorNewTabPageAddShortcutBackground, + SK_ColorWHITE, gfx::kGoogleGrey900); + +- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; ++ mixer[kColorComposeboxBackground] = {dark_mode ? ui::kColorSysBaseContainer : SK_ColorWHITE}; + mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; + mixer[kColorComposeboxFont] = { + dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) +@@ -400,15 +400,28 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + SkColorSetRGB(0xD3, 0xE3, 0xFD)}; + mixer[kColorSearchboxAnswerIconForeground] = { + SkColorSetRGB(0x04, 0x1E, 0x49)}; +- mixer[kColorSearchboxBackground] = {SK_ColorWHITE}; +- mixer[kColorSearchboxBackgroundHovered] = {SK_ColorWHITE}; ++ mixer[kColorSearchboxBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxBackgroundHovered] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(SK_ColorBLACK)}; ++ mixer[kColorSearchboxPlaceholder] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxLensVoiceIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorSearchboxBorder] = { + key.contrast_mode == ui::ColorProviderKey::ContrastMode::kHigh + ? kColorLocationBarBorder + : gfx::kGoogleGrey300}; +- mixer[kColorSearchboxForeground] = {SK_ColorBLACK}; +- mixer[kColorSearchboxPlaceholder] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsBackground] = {SK_ColorWHITE}; + mixer[kColorSearchboxResultsBackgroundHovered] = + ui::SetAlpha(gfx::kGoogleGrey900, + /* 10% opacity */ 0.1 * SK_AlphaOPAQUE); +@@ -420,16 +433,39 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + SkColorSetRGB(0x0B, 0x57, 0xD0)}; + mixer[kColorSearchboxResultsActionChipFocusOutline] = { + SkColorSetRGB(0x0B, 0x57, 0xD0)}; +- mixer[kColorSearchboxResultsDimSelected] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsFocusIndicator] = {gfx::kGoogleBlue600}; +- mixer[kColorSearchboxResultsForeground] = {SK_ColorBLACK}; +- mixer[kColorSearchboxResultsForegroundDimmed] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIconSelected] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsUrl] = {gfx::kGoogleBlue700}; +- mixer[kColorSearchboxResultsUrlSelected] = {gfx::kGoogleBlue700}; +- mixer[kColorSearchboxSearchIconBackground] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIcon] = {gfx::kGoogleGrey700}; +- mixer[kColorSearchboxResultsIconFocusedOutline] = {gfx::kGoogleBlue600}; ++ mixer[kColorSearchboxResultsDimSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsFocusIndicator] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue600}; ++ mixer[kColorSearchboxResultsForeground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ : ui::ColorTransform(SK_ColorBLACK)}; ++ mixer[kColorSearchboxResultsForegroundDimmed] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconContainerBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) ++ : ui::ColorTransform(SK_ColorWHITE)}; ++ mixer[kColorSearchboxResultsUrl] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue700}; ++ mixer[kColorSearchboxResultsUrlSelected] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue700}; ++ mixer[kColorSearchboxSearchIconBackground] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIcon] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) ++ : gfx::kGoogleGrey700}; ++ mixer[kColorSearchboxResultsIconFocusedOutline] = ++ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) ++ : gfx::kGoogleBlue600}; + mixer[kColorSearchboxShadow] = + ui::SetAlpha(gfx::kGoogleGrey900, + (dark_mode ? /* % opacity */ 0.32 : 0.28) * SK_AlphaOPAQUE); +diff --git a/ui/color/core_default_color_mixer.cc b/ui/color/core_default_color_mixer.cc +index 54cb33c7e3f91..41446d2a935c5 100644 +--- a/ui/color/core_default_color_mixer.cc ++++ b/ui/color/core_default_color_mixer.cc +@@ -25,7 +25,7 @@ void AddCoreDefaultColorMixer(ColorProvider* provider, + DVLOG(2) << "Adding CoreDefaultColorMixer to ColorProvider for " + << (dark_mode ? "Dark" : "Light") << " window."; + ColorMixer& mixer = provider->AddMixer(); +- mixer[kColorAccent] = {dark_mode ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600}; ++ mixer[kColorAccent] = {dark_mode ? SK_ColorWHITE : SK_ColorWHITE}; + // 4.5 and 7.0 approximate the default light and dark theme contrasts of + // accent-against-primary-background. + mixer[kColorAccentWithGuaranteedContrastAtopPrimaryBackground] = +diff --git a/ui/color/mac/native_color_mixers_mac.mm b/ui/color/mac/native_color_mixers_mac.mm +index fb2d49fe27f3d..c740e3b5fa995 100644 +--- a/ui/color/mac/native_color_mixers_mac.mm ++++ b/ui/color/mac/native_color_mixers_mac.mm +@@ -99,11 +99,11 @@ void AddNativeUiColorMixer(ColorProvider* provider, + + mixer[kColorTableBackgroundAlternate] = {skia::NSSystemColorToSkColor( + NSColor.alternatingContentBackgroundColors[1])}; +- if (!key.user_color.has_value()) { +- mixer[kColorSysStateFocusRing] = PickGoogleColor( +- skia::NSSystemColorToSkColor(NSColor.keyboardFocusIndicatorColor), +- kColorSysBase, color_utils::kMinimumVisibleContrastRatio); + ++ // Override focus ring color: white in dark mode, black in light mode ++ mixer[kColorSysStateFocusRing] = {properties.dark ? SK_ColorWHITE : SK_ColorBLACK}; ++ ++ if (!key.user_color.has_value()) { + const SkColor system_highlight_color = + skia::NSSystemColorToSkColor(NSColor.selectedTextBackgroundColor); + mixer[kColorTextSelectionBackground] = {system_highlight_color}; +diff --git a/ui/color/ref_color_mixer.cc b/ui/color/ref_color_mixer.cc +index 3eb2f1053b895..a57a92344f27a 100644 +--- a/ui/color/ref_color_mixer.cc ++++ b/ui/color/ref_color_mixer.cc +@@ -25,36 +25,36 @@ namespace ui { + void AddBaselinePalette(ColorProvider* provider) { + ColorMixer& mixer = provider->AddMixer(); + mixer[kColorRefPrimary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +- mixer[kColorRefPrimary10] = {SkColorSetRGB(0x04, 0x1E, 0x49)}; +- mixer[kColorRefPrimary20] = {SkColorSetRGB(0x06, 0x2E, 0x6F)}; +- mixer[kColorRefPrimary25] = {SkColorSetRGB(0x07, 0x38, 0x88)}; +- mixer[kColorRefPrimary30] = {SkColorSetRGB(0x08, 0x42, 0xA0)}; +- mixer[kColorRefPrimary40] = {SkColorSetRGB(0x0B, 0x57, 0xD0)}; +- mixer[kColorRefPrimary50] = {SkColorSetRGB(0x1B, 0x6E, 0xF3)}; +- mixer[kColorRefPrimary60] = {SkColorSetRGB(0x4C, 0x8D, 0xF6)}; +- mixer[kColorRefPrimary70] = {SkColorSetRGB(0x7C, 0xAC, 0xF8)}; +- mixer[kColorRefPrimary80] = {SkColorSetRGB(0xA8, 0xC7, 0xFA)}; +- mixer[kColorRefPrimary90] = {SkColorSetRGB(0xD3, 0xE3, 0xFD)}; +- mixer[kColorRefPrimary95] = {SkColorSetRGB(0xEC, 0xF3, 0xFE)}; +- mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFB, 0xFF)}; ++ mixer[kColorRefPrimary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; ++ mixer[kColorRefPrimary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; ++ mixer[kColorRefPrimary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; ++ mixer[kColorRefPrimary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; ++ mixer[kColorRefPrimary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; ++ mixer[kColorRefPrimary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; ++ mixer[kColorRefPrimary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; ++ mixer[kColorRefPrimary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; ++ mixer[kColorRefPrimary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; ++ mixer[kColorRefPrimary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; ++ mixer[kColorRefPrimary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; ++ mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; + mixer[kColorRefPrimary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; + + mixer[kColorRefSecondary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +- mixer[kColorRefSecondary10] = {SkColorSetRGB(0x00, 0x1D, 0x35)}; +- mixer[kColorRefSecondary12] = {SkColorSetRGB(0x00, 0x22, 0x38)}; +- mixer[kColorRefSecondary15] = {SkColorSetRGB(0x00, 0x28, 0x45)}; +- mixer[kColorRefSecondary20] = {SkColorSetRGB(0x00, 0x33, 0x55)}; +- mixer[kColorRefSecondary25] = {SkColorSetRGB(0x00, 0x3f, 0x66)}; +- mixer[kColorRefSecondary30] = {SkColorSetRGB(0x00, 0x4A, 0x77)}; +- mixer[kColorRefSecondary35] = {SkColorSetRGB(0x00, 0x57, 0x89)}; +- mixer[kColorRefSecondary40] = {SkColorSetRGB(0x00, 0x63, 0x9B)}; +- mixer[kColorRefSecondary50] = {SkColorSetRGB(0x04, 0x7D, 0xB7)}; +- mixer[kColorRefSecondary60] = {SkColorSetRGB(0x39, 0x98, 0xD3)}; +- mixer[kColorRefSecondary70] = {SkColorSetRGB(0x5A, 0xB3, 0xF0)}; +- mixer[kColorRefSecondary80] = {SkColorSetRGB(0x7F, 0xCF, 0xFF)}; +- mixer[kColorRefSecondary90] = {SkColorSetRGB(0xC2, 0xE7, 0xFF)}; +- mixer[kColorRefSecondary95] = {SkColorSetRGB(0xDF, 0xF3, 0xFF)}; +- mixer[kColorRefSecondary99] = {SkColorSetRGB(0xF7, 0xFC, 0xFF)}; ++ mixer[kColorRefSecondary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; ++ mixer[kColorRefSecondary12] = {SkColorSetRGB(0x1F, 0x1F, 0x1F)}; ++ mixer[kColorRefSecondary15] = {SkColorSetRGB(0x26, 0x26, 0x26)}; ++ mixer[kColorRefSecondary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; ++ mixer[kColorRefSecondary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; ++ mixer[kColorRefSecondary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; ++ mixer[kColorRefSecondary35] = {SkColorSetRGB(0x59, 0x59, 0x59)}; ++ mixer[kColorRefSecondary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; ++ mixer[kColorRefSecondary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; ++ mixer[kColorRefSecondary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; ++ mixer[kColorRefSecondary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; ++ mixer[kColorRefSecondary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; ++ mixer[kColorRefSecondary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; ++ mixer[kColorRefSecondary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; ++ mixer[kColorRefSecondary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; + mixer[kColorRefSecondary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; + + mixer[kColorRefTertiary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; +diff --git a/ui/color/sys_color_mixer.cc b/ui/color/sys_color_mixer.cc +index 4745b7f50a28b..6cef161038ae8 100644 +--- a/ui/color/sys_color_mixer.cc ++++ b/ui/color/sys_color_mixer.cc +@@ -31,6 +31,8 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, + : kColorRefSecondary30}; + mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefPrimary30 + : kColorRefPrimary90}; ++ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; + mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefPrimary10 + : kColorRefPrimary90}; + mixer[kColorSysNeutralContainer] = {dark_mode ? kColorRefNeutralVariant15 +@@ -39,18 +41,18 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, + : kColorRefPrimary90}; + + // Chrome surfaces. +- mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary25 ++ mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary10 + : kColorRefNeutral98}; +- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary15 ++ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary25 + : kColorSysSurface4}; + mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefSecondary25 + : kColorRefNeutral98}; + +- mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary12 ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary10 + : kColorRefSecondary90}; + mixer[kColorSysHeaderContainer] = {dark_mode ? kColorRefSecondary25 + : kColorRefPrimary95}; +- mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral25 ++ mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral99}; + mixer[kColorSysOnHeaderDivider] = {dark_mode ? kColorRefSecondary25 + : kColorRefPrimary80}; +@@ -78,12 +80,12 @@ void AddGrayscaleSysColorOverrides(ColorMixer& mixer, + + // General + mixer[kColorSysOnSurfacePrimary] = {dark_mode ? kColorRefNeutral90 +- : kColorRefNeutral10}; +- mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 +- : kColorRefNeutral90}; ++ : kColorRefNeutral10}; ++mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 ++: kColorRefNeutral90}; + + // Chrome surfaces. +- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral90}; + mixer[kColorSysHeaderInactive] = { + dark_mode ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) +@@ -116,24 +118,24 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + ColorMixer& mixer = provider->AddMixer(); + + // Primary. +- mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary80 +- : kColorRefPrimary40}; +- mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary20 +- : kColorRefPrimary100}; +- mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary30 +- : kColorRefPrimary90}; +- mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary90 +- : kColorRefPrimary10}; ++ mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; ++ mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary10 ++ : kColorRefPrimary90}; ++ mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary90 ++ : kColorRefPrimary10}; ++ mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary10 ++ : kColorRefPrimary90}; + + // Secondary. +- mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary80 +- : kColorRefSecondary40}; +- mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary20 +- : kColorRefSecondary100}; +- mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary30 +- : kColorRefSecondary90}; +- mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary90 +- : kColorRefSecondary10}; ++ mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary90 ++ : kColorRefSecondary10}; ++ mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary10 ++ : kColorRefSecondary90}; ++ mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary90 ++ : kColorRefSecondary10}; ++ mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary10 ++ : kColorRefSecondary90}; + // Tertiary. + mixer[kColorSysTertiary] = {dark_mode ? kColorRefTertiary80 + : kColorRefTertiary40}; +@@ -179,8 +181,8 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + mixer[kColorSysSurface] = {dark_mode ? kColorRefNeutral10 + : kColorRefNeutral100}; + mixer[kColorSysSurfaceNumberedForeground] = { +- dark_mode ? SkColorSetRGB(0xD1, 0xE1, 0xFF) +- : SkColorSetRGB(0x69, 0x91, 0xD6)}; ++ dark_mode ? kColorRefNeutral90 ++ : kColorRefNeutral10}; + mixer[kColorSysSurface1] = AlphaBlend({kColorSysSurfaceNumberedForeground}, + {kColorSysSurface}, 0x0C); + mixer[kColorSysSurface2] = AlphaBlend({kColorSysSurfaceNumberedForeground}, +@@ -202,10 +204,10 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + mixer[kColorSysOnSurfacePrimaryInactive] = {dark_mode ? kColorRefNeutral90 + : kColorRefNeutral10}; + +- mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary30 +- : kColorRefPrimary90}; +- mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary90 +- : kColorRefPrimary10}; ++ mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary100 ++ : kColorRefPrimary0}; ++ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary0 ++ : kColorRefPrimary100}; + mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefSecondary10 + : kColorRefPrimary90}; + mixer[kColorSysOnBaseTonalContainer] = {dark_mode ? kColorRefSecondary90 +@@ -220,14 +222,13 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { + : kColorRefPrimary90}; + + // Chrome surfaces. +- mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral25 : kColorRefNeutral100}; +- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral15 +- : kColorSysSurface4}; ++ mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral10 : kColorRefNeutral100}; ++ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral25 : kColorSysSurface4}; + mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefNeutral25 + : kColorRefNeutral100}; + +- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 +- : kColorRefPrimary90}; ++ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 ++ : kColorRefNeutral90}; + mixer[kColorSysHeaderInactive] = { + dark_mode + ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) +diff --git a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts +index 6c77613866851..8c2a9b66df274 100644 +--- a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts ++++ b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts +@@ -29,26 +29,26 @@ export const DARK_DEFAULT_COLOR: Color = { + }; + + export const LIGHT_BASELINE_BLUE_COLOR: Color = { +- background: {value: 0xff0b57d0}, +- foreground: {value: 0xffd3e3fd}, +- base: {value: 0xffc7c7c7}, ++ background: {value: 0xff000000}, ++ foreground: {value: 0xffffffff}, ++ base: {value: 0xff606060}, + }; + + export const DARK_BASELINE_BLUE_COLOR: Color = { +- background: {value: 0xffa8c7fa}, +- foreground: {value: 0xff0842a0}, ++ background: {value: 0xffffffff}, ++ foreground: {value: 0xff000000}, + base: {value: 0xff757575}, + }; + + export const LIGHT_BASELINE_GREY_COLOR: Color = { +- background: {value: 0xff0b57d0}, +- foreground: {value: 0xffe3e3e3}, +- base: {value: 0xffc7c7c7}, ++ background: {value: 0xff000000}, ++ foreground: {value: 0xffffffff}, ++ base: {value: 0xff606060}, + }; + + export const DARK_BASELINE_GREY_COLOR: Color = { +- background: {value: 0xffa8c7fa}, +- foreground: {value: 0xff474747}, ++ background: {value: 0xffffffff}, ++ foreground: {value: 0xff000000}, + base: {value: 0xff757575}, + }; + diff --git a/chromium/patches/theme/theme-styling.patch b/chromium/patches/theme/theme-styling.patch new file mode 100644 index 0000000..d628681 --- /dev/null +++ b/chromium/patches/theme/theme-styling.patch @@ -0,0 +1,697 @@ +diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd +index 87c3c8382e602..d38aa879d082b 100644 +--- a/chrome/app/theme/theme_resources.grd ++++ b/chrome/app/theme/theme_resources.grd +@@ -160,6 +160,7 @@ + + + ++ + + + +diff --git a/chrome/browser/resources/new_tab_page/app.css b/chrome/browser/resources/new_tab_page/app.css +index e478fea59f056..7f971831f25b6 100644 +--- a/chrome/browser/resources/new_tab_page/app.css ++++ b/chrome/browser/resources/new_tab_page/app.css +@@ -57,18 +57,18 @@ + */ + :host([realbox-can-show-secondary-side][realbox-had-secondary-side]), + :host([realbox-can-show-secondary-side]) { +- --ntp-search-box-width: 746px; ++ --ntp-search-box-width: 900px; + } + + @media (min-width: 560px) { + :host { +- --ntp-search-box-width: 449px; ++ --ntp-search-box-width: 600px; + } + } + + @media (min-width: 672px) { + :host { +- --ntp-search-box-width: 561px; ++ --ntp-search-box-width: 750px; + } + } + +diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts +index 167ae9b24c89f..b3e65a5d99076 100644 +--- a/chrome/browser/resources/new_tab_page/app.ts ++++ b/chrome/browser/resources/new_tab_page/app.ts +@@ -1160,10 +1160,8 @@ export class AppElement extends AppElementBase { + } + + protected computeShowBrowserPromo_(): boolean { +- return !this.modulesEnabled_ || +- (this.modulesLoadedStatus_ !== +- ModuleLoadStatus.MODULE_LOAD_IN_PROGRESS && +- !this.modulesShownToUser); ++ // Disabled: Don't show "Make OpenBrowser Yours" setup list ++ return false; + } + + protected recordBrowserPromoMetrics_() { +diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc +index 8634cbb4dc17a..ef53ad2540d79 100644 +--- a/chrome/browser/themes/theme_service_factory.cc ++++ b/chrome/browser/themes/theme_service_factory.cc +@@ -139,6 +139,7 @@ void ThemeServiceFactory::RegisterProfilePrefs( + registry->RegisterIntegerPref( + prefs::kDeprecatedUserColorDoNotUse, SK_ColorTRANSPARENT, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); ++ // Use transparent to indicate no custom color (will use baseline grayscale) + registry->RegisterIntegerPref(prefs::kUserColor, SK_ColorTRANSPARENT); + registry->RegisterIntegerPref( + prefs::kDeprecatedBrowserColorVariantDoNotUse, +diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +index 350f052b92aef..36dec424c89f2 100644 +--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc ++++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc +@@ -407,7 +407,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) + : ui::ColorTransform(SK_ColorWHITE)}; + mixer[kColorSearchboxForeground] = +- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) + : ui::ColorTransform(SK_ColorBLACK)}; + mixer[kColorSearchboxPlaceholder] = + {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) +@@ -440,7 +440,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, + {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) + : gfx::kGoogleBlue600}; + mixer[kColorSearchboxResultsForeground] = +- {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) ++ {dark_mode ? ui::ColorTransform(SK_ColorWHITE) + : ui::ColorTransform(SK_ColorBLACK)}; + mixer[kColorSearchboxResultsForegroundDimmed] = + {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) +diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +index 3544f1b569ee1..760b5a59e82df 100644 +--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc ++++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +@@ -626,7 +626,7 @@ gfx::RoundedCornersF IconLabelBubbleView::GetCornerRadii() const { + if (radii_.has_value()) { + return radii_.value(); + } +- return gfx::RoundedCornersF(GetPreferredSize().height() / 2); ++ return gfx::RoundedCornersF(4); + } + + void IconLabelBubbleView::SetCornerRadii(const gfx::RoundedCornersF& radii) { +diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc +index 2dbe7d318cd7b..989abffe08143 100644 +--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc ++++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc +@@ -245,7 +245,7 @@ LocationBarView::LocationBarView(Browser* browser, + !v->GetOmniboxController()->IsPopupOpen(); + })); + views::FocusRing::Get(this)->SetOutsetFocusRingDisabled(true); +- views::InstallPillHighlightPathGenerator(this); ++ views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), 8); + + #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) + if (features::IsOsLevelGeolocationPermissionSupportEnabled()) { +diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc +index d5306a85b1e0c..40c9d0ffd3971 100644 +--- a/chrome/browser/ui/views/tabs/tab.cc ++++ b/chrome/browser/ui/views/tabs/tab.cc +@@ -372,8 +372,20 @@ void Tab::Layout(PassKey) { + + // The bounds for the favicon will include extra width for the attention + // indicator, but visually it will be smaller at kFaviconSize wide. +- gfx::Rect favicon_bounds(start, contents_rect.y(), 0, 0); ++ ++ gfx::Rect favicon_bounds; + if (showing_icon_) { ++ const gfx::Size icon_size = icon_->GetPreferredSize(); ++ const gfx::Insets icon_insets = icon_->GetInsets(); ++ ++ // Center the favicon vertically so its middle aligns with the content area ++ // middle. We need to add the inset back because Inset(-insets) will ++ // subtract it later. ++ const int content_middle_y = contents_rect.y() + contents_rect.height() / 2; ++ const int favicon_y = content_middle_y - icon_size.height() / 2 + icon_insets.top(); ++ ++ favicon_bounds = gfx::Rect(start, favicon_y, 0, 0); ++ + if (center_icon_) { + // When centering the favicon, the favicon is allowed to escape the normal + // contents rect. +@@ -389,7 +401,9 @@ void Tab::Layout(PassKey) { + + // Add space for insets outside the favicon bounds. + favicon_bounds.Inset(-icon_->GetInsets()); +- favicon_bounds.set_size(icon_->GetPreferredSize()); ++ favicon_bounds.set_size(icon_size); ++ } else { ++ favicon_bounds = gfx::Rect(start, contents_rect.y(), 0, 0); + } + icon_->SetBoundsRect(favicon_bounds); + icon_->SetVisible(showing_icon_); +diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +index 832ca90c1538c..ce053294b3ad0 100644 +--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc ++++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +@@ -616,13 +616,8 @@ void NewTabPageHandler::GetMostVisitedSettings( + } + + void NewTabPageHandler::GetDoodle(GetDoodleCallback callback) { +- search_provider_logos::LogoCallbacks callbacks; +- callbacks.on_cached_encoded_logo_available = +- base::BindOnce(&NewTabPageHandler::OnLogoAvailable, +- weak_ptr_factory_.GetWeakPtr(), std::move(callback)); +- // This will trigger re-downloading the doodle and caching it. This means a +- // new doodle will be returned on subsequent NTP loads. +- logo_service_->GetLogo(std::move(callbacks), /*for_webui_ntp=*/true); ++ // Disable Google doodle downloading - always return null to use local logo ++ std::move(callback).Run(nullptr); + } + + void NewTabPageHandler::UpdatePromoData() { +diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc +index 6d2ea1d68430b..406d9402d41e1 100644 +--- a/components/search/ntp_features.cc ++++ b/components/search/ntp_features.cc +@@ -98,7 +98,7 @@ BASE_FEATURE(kNtpDummyModules, base::FEATURE_DISABLED_BY_DEFAULT); + + // If enabled, Google Drive module will be shown. + // This is a kill switch. Keep indefinitely. +-BASE_FEATURE(kNtpDriveModule, base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpDriveModule, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, the NTP Drive module does not require sync. + BASE_FEATURE(kNtpDriveModuleHistorySyncRequirement, +@@ -121,7 +121,7 @@ BASE_FEATURE(kNtpMiddleSlotPromo, base::FEATURE_ENABLED_BY_DEFAULT); + + // If enabled, middle slot promo will be dismissed from New Tab Page until new + // promo message is populated +-BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_DISABLED_BY_DEFAULT); ++BASE_FEATURE(kNtpMiddleSlotPromoDismissal, base::FEATURE_ENABLED_BY_DEFAULT); + + // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". + // This is used for an emergency Finch param. Keep indefinitely. +diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h +index d8c168edc6c92..2d8243d947b94 100644 +--- a/ui/native_theme/native_theme.h ++++ b/ui/native_theme/native_theme.h +@@ -602,7 +602,7 @@ class COMPONENT_EXPORT(NATIVE_THEME) NativeTheme { + std::optional user_color_; + std::optional scheme_variant_; + ColorProviderKey::UserColorSource preferred_color_source_ = +- ColorProviderKey::UserColorSource::kAccent; ++ ColorProviderKey::UserColorSource::kBaseline; + base::TimeDelta caret_blink_interval_; + + raw_ptr associated_web_instance_ = nullptr; +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.css b/ui/webui/resources/cr_components/searchbox/searchbox.css +index dc4fdb93e0fa3..5ca09ff564360 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox.css +@@ -12,7 +12,7 @@ + :host { + /* Embedders should define --cr-searchbox-min-width. */ + --cr-searchbox-width: var(--cr-searchbox-min-width); +- --cr-searchbox-border-radius: calc(0.5 * var(--cr-searchbox-height)); ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-icon-width: 26px; + --cr-searchbox-inner-icon-margin: 8px; + --cr-searchbox-voice-icon-offset: 16px; +@@ -274,11 +274,29 @@ cr-searchbox-icon { + } + + :host(:not([use-webkit-search-icons_])) #voiceSearchButton { +- background-image: url(//resources/cr_components/searchbox/icons/mic.svg); ++ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/mic.svg); ++ -webkit-mask-position: center; ++ -webkit-mask-repeat: no-repeat; ++ -webkit-mask-size: 21px 21px; + } + + :host(:not([use-webkit-search-icons_])) #lensSearchButton { +- background-image: url(//resources/cr_components/searchbox/icons/camera.svg); ++ -webkit-mask-image: url(//resources/cr_components/searchbox/icons/camera.svg); ++ -webkit-mask-position: center; ++ -webkit-mask-repeat: no-repeat; ++ -webkit-mask-size: 21px 21px; ++} ++ ++/* White icons in dark mode */ ++:host(:not([use-webkit-search-icons_])[is-dark]) #voiceSearchButton, ++:host(:not([use-webkit-search-icons_])[is-dark]) #lensSearchButton { ++ background-color: white; ++} ++ ++/* Black icons in light mode */ ++:host(:not([use-webkit-search-icons_]):not([is-dark])) #voiceSearchButton, ++:host(:not([use-webkit-search-icons_]):not([is-dark])) #lensSearchButton { ++ background-color: black; + } + + :host([use-webkit-search-icons_]) #voiceSearchButton { +@@ -373,7 +391,7 @@ search-animated-glow { + } + + :host([ntp-realbox-next-enabled]) { +- --cr-searchbox-border-radius: 26px; ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-dropdown-padding-bottom: 12px; + /* Cannot touch this searchbox icon size var; + it's used by the rainbow outline AI button class in +@@ -540,7 +558,7 @@ search-animated-glow { + } + + :host([searchbox-layout-mode='Compact']) { +- --cr-searchbox-border-radius: 30px; ++ --cr-searchbox-border-radius: 8px; + --cr-searchbox-dropdown-padding-bottom: 10px; + --cr-searchbox-dropdown-padding-top: 10px; + --cr-searchbox-height: 56px; +diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_match.css b/ui/webui/resources/cr_components/searchbox/searchbox_match.css +index 514d780649bba..48fe44b9e8788 100644 +--- a/ui/webui/resources/cr_components/searchbox/searchbox_match.css ++++ b/ui/webui/resources/cr_components/searchbox/searchbox_match.css +@@ -221,13 +221,14 @@ + + .match { + font-weight: var(--cr-searchbox-match-font-weight, 600); ++ color: var(--color-searchbox-results-foreground); + } + + /* In the lens side panel searchbox, the typed prefix of the match should + * have a different color than the rest of the autocomplete suggestion. */ + :host(:not([is-top-chrome-searchbox_])) #contents span:not(.match), + #ellipsis { +- color: var(--color-searchbox-results-typed-prefix, --color-searchbox-results-foreground); ++ color: var(--color-searchbox-results-foreground); + } + + /* Used to override contents color in zero prefix matches */ +diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +index 735615a4ba785..d95689b8b1196 100644 +--- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts ++++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html.ts +@@ -15,7 +15,8 @@ export function getHtml(this: CrDrawerElement) { + + + ++ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, ++ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> + + + ++ srcset="chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@1x 1x, ++ chrome://theme/IDR_PRODUCT_LOGO_32_WHITE@2x 2x"> + GetColor(ui::color_id))) ++ ++ // Reference colors - Primary palette ++ ADD_COLOR(kColorRefPrimary0); ++ ADD_COLOR(kColorRefPrimary10); ++ ADD_COLOR(kColorRefPrimary20); ++ ADD_COLOR(kColorRefPrimary25); ++ ADD_COLOR(kColorRefPrimary30); ++ ADD_COLOR(kColorRefPrimary40); ++ ADD_COLOR(kColorRefPrimary50); ++ ADD_COLOR(kColorRefPrimary60); ++ ADD_COLOR(kColorRefPrimary70); ++ ADD_COLOR(kColorRefPrimary80); ++ ADD_COLOR(kColorRefPrimary90); ++ ADD_COLOR(kColorRefPrimary95); ++ ADD_COLOR(kColorRefPrimary99); ++ ADD_COLOR(kColorRefPrimary100); ++ ++ // Reference colors - Secondary palette ++ ADD_COLOR(kColorRefSecondary0); ++ ADD_COLOR(kColorRefSecondary10); ++ ADD_COLOR(kColorRefSecondary12); ++ ADD_COLOR(kColorRefSecondary15); ++ ADD_COLOR(kColorRefSecondary20); ++ ADD_COLOR(kColorRefSecondary25); ++ ADD_COLOR(kColorRefSecondary30); ++ ADD_COLOR(kColorRefSecondary35); ++ ADD_COLOR(kColorRefSecondary40); ++ ADD_COLOR(kColorRefSecondary50); ++ ADD_COLOR(kColorRefSecondary60); ++ ADD_COLOR(kColorRefSecondary70); ++ ADD_COLOR(kColorRefSecondary80); ++ ADD_COLOR(kColorRefSecondary90); ++ ADD_COLOR(kColorRefSecondary95); ++ ADD_COLOR(kColorRefSecondary99); ++ ADD_COLOR(kColorRefSecondary100); ++ ++ // Reference colors - Tertiary palette ++ ADD_COLOR(kColorRefTertiary0); ++ ADD_COLOR(kColorRefTertiary10); ++ ADD_COLOR(kColorRefTertiary20); ++ ADD_COLOR(kColorRefTertiary30); ++ ADD_COLOR(kColorRefTertiary40); ++ ADD_COLOR(kColorRefTertiary50); ++ ADD_COLOR(kColorRefTertiary60); ++ ADD_COLOR(kColorRefTertiary70); ++ ADD_COLOR(kColorRefTertiary80); ++ ADD_COLOR(kColorRefTertiary90); ++ ADD_COLOR(kColorRefTertiary95); ++ ADD_COLOR(kColorRefTertiary99); ++ ADD_COLOR(kColorRefTertiary100); ++ ++ // Reference colors - Error palette ++ ADD_COLOR(kColorRefError0); ++ ADD_COLOR(kColorRefError10); ++ ADD_COLOR(kColorRefError20); ++ ADD_COLOR(kColorRefError30); ++ ADD_COLOR(kColorRefError40); ++ ADD_COLOR(kColorRefError50); ++ ADD_COLOR(kColorRefError60); ++ ADD_COLOR(kColorRefError70); ++ ADD_COLOR(kColorRefError80); ++ ADD_COLOR(kColorRefError90); ++ ADD_COLOR(kColorRefError95); ++ ADD_COLOR(kColorRefError99); ++ ADD_COLOR(kColorRefError100); ++ ++ // Reference colors - Neutral palette ++ ADD_COLOR(kColorRefNeutral0); ++ ADD_COLOR(kColorRefNeutral4); ++ ADD_COLOR(kColorRefNeutral6); ++ ADD_COLOR(kColorRefNeutral8); ++ ADD_COLOR(kColorRefNeutral10); ++ ADD_COLOR(kColorRefNeutral12); ++ ADD_COLOR(kColorRefNeutral15); ++ ADD_COLOR(kColorRefNeutral17); ++ ADD_COLOR(kColorRefNeutral20); ++ ADD_COLOR(kColorRefNeutral22); ++ ADD_COLOR(kColorRefNeutral24); ++ ADD_COLOR(kColorRefNeutral25); ++ ADD_COLOR(kColorRefNeutral30); ++ ADD_COLOR(kColorRefNeutral40); ++ ADD_COLOR(kColorRefNeutral50); ++ ADD_COLOR(kColorRefNeutral60); ++ ADD_COLOR(kColorRefNeutral70); ++ ADD_COLOR(kColorRefNeutral80); ++ ADD_COLOR(kColorRefNeutral87); ++ ADD_COLOR(kColorRefNeutral90); ++ ADD_COLOR(kColorRefNeutral92); ++ ADD_COLOR(kColorRefNeutral94); ++ ADD_COLOR(kColorRefNeutral95); ++ ADD_COLOR(kColorRefNeutral96); ++ ADD_COLOR(kColorRefNeutral98); ++ ADD_COLOR(kColorRefNeutral99); ++ ADD_COLOR(kColorRefNeutral100); ++ ++ // Reference colors - Neutral Variant palette ++ ADD_COLOR(kColorRefNeutralVariant0); ++ ADD_COLOR(kColorRefNeutralVariant10); ++ ADD_COLOR(kColorRefNeutralVariant20); ++ ADD_COLOR(kColorRefNeutralVariant30); ++ ADD_COLOR(kColorRefNeutralVariant40); ++ ADD_COLOR(kColorRefNeutralVariant50); ++ ADD_COLOR(kColorRefNeutralVariant60); ++ ADD_COLOR(kColorRefNeutralVariant70); ++ ADD_COLOR(kColorRefNeutralVariant80); ++ ADD_COLOR(kColorRefNeutralVariant90); ++ ADD_COLOR(kColorRefNeutralVariant95); ++ ADD_COLOR(kColorRefNeutralVariant99); ++ ADD_COLOR(kColorRefNeutralVariant100); ++ ++ // System colors - Primary ++ ADD_COLOR(kColorSysPrimary); ++ ADD_COLOR(kColorSysOnPrimary); ++ ADD_COLOR(kColorSysPrimaryContainer); ++ ADD_COLOR(kColorSysOnPrimaryContainer); ++ ++ // System colors - Secondary ++ ADD_COLOR(kColorSysSecondary); ++ ADD_COLOR(kColorSysOnSecondary); ++ ADD_COLOR(kColorSysSecondaryContainer); ++ ADD_COLOR(kColorSysOnSecondaryContainer); ++ ++ // System colors - Tertiary ++ ADD_COLOR(kColorSysTertiary); ++ ADD_COLOR(kColorSysOnTertiary); ++ ADD_COLOR(kColorSysTertiaryContainer); ++ ADD_COLOR(kColorSysOnTertiaryContainer); ++ ++ // System colors - Error ++ ADD_COLOR(kColorSysError); ++ ADD_COLOR(kColorSysOnError); ++ ADD_COLOR(kColorSysErrorContainer); ++ ADD_COLOR(kColorSysOnErrorContainer); ++ ++ // System colors - Surface ++ ADD_COLOR(kColorSysSurface); ++ ADD_COLOR(kColorSysOnSurface); ++ ADD_COLOR(kColorSysSurfaceVariant); ++ ADD_COLOR(kColorSysOnSurfaceVariant); ++ ADD_COLOR(kColorSysSurface1); ++ ADD_COLOR(kColorSysSurface2); ++ ADD_COLOR(kColorSysSurface3); ++ ADD_COLOR(kColorSysSurface4); ++ ADD_COLOR(kColorSysSurface5); ++ ++ // System colors - Background ++ ADD_COLOR(kColorSysOnSurfaceSecondary); ++ ADD_COLOR(kColorSysOnSurfaceSubtle); ++ ADD_COLOR(kColorSysOnSurfacePrimary); ++ ++ // System colors - Tonal Container (YOUR EXAMPLE!) ++ ADD_COLOR(kColorSysTonalContainer); ++ ADD_COLOR(kColorSysOnTonalContainer); ++ ADD_COLOR(kColorSysBaseTonalContainer); ++ ADD_COLOR(kColorSysOnBaseTonalContainer); ++ ++ // System colors - Outline ++ ADD_COLOR(kColorSysTonalOutline); ++ ADD_COLOR(kColorSysNeutralOutline); ++ ADD_COLOR(kColorSysNeutralContainer); ++ ADD_COLOR(kColorSysDivider); ++ ++ // System colors - Chrome surfaces ++ ADD_COLOR(kColorSysBase); ++ ADD_COLOR(kColorSysBaseContainer); ++ ADD_COLOR(kColorSysBaseContainerElevated); ++ ADD_COLOR(kColorSysHeader); ++ ADD_COLOR(kColorSysHeaderContainer); ++ ++ // System colors - State ++ ADD_COLOR(kColorSysStateHoverOnProminent); ++ ADD_COLOR(kColorSysStateHoverOnSubtle); ++ ADD_COLOR(kColorSysStateFocusRing); ++ ADD_COLOR(kColorSysStateDisabled); ++ ADD_COLOR(kColorSysStateDisabledContainer); ++ ++ // Additional essential colors that were missing ++ ADD_COLOR(kColorPrimaryBackground); ++ ADD_COLOR(kColorPrimaryForeground); ++ ADD_COLOR(kColorSecondaryForeground); ++ ADD_COLOR(kColorDialogBackground); ++ ADD_COLOR(kColorDialogForeground); ++ ADD_COLOR(kColorBubbleBackground); ++ ADD_COLOR(kColorBubbleBorder); ++ ADD_COLOR(kColorButtonBackground); ++ ADD_COLOR(kColorButtonForeground); ++ ADD_COLOR(kColorButtonBackgroundProminent); ++ ADD_COLOR(kColorButtonForegroundProminent); ++ ADD_COLOR(kColorLabelForeground); ++ ADD_COLOR(kColorLabelForegroundSecondary); ++ ADD_COLOR(kColorLabelForegroundDisabled); ++ ADD_COLOR(kColorLinkForeground); ++ ADD_COLOR(kColorLinkForegroundPressed); ++ ADD_COLOR(kColorMenuBackground); ++ ADD_COLOR(kColorMenuBorder); ++ ADD_COLOR(kColorMenuItemForeground); ++ ADD_COLOR(kColorMenuItemBackgroundSelected); ++ ADD_COLOR(kColorMenuSeparator); ++ ADD_COLOR(kColorSeparator); ++ ADD_COLOR(kColorTextfieldBackground); ++ ADD_COLOR(kColorTextfieldForeground); ++ ADD_COLOR(kColorTooltipBackground); ++ ADD_COLOR(kColorTooltipForeground); ++ ADD_COLOR(kColorIcon); ++ ADD_COLOR(kColorIconSecondary); ++ ADD_COLOR(kColorIconDisabled); ++ ADD_COLOR(kColorSliderThumb); ++ ADD_COLOR(kColorSliderTrack); ++ ADD_COLOR(kColorAccent); ++ ADD_COLOR(kColorDisabledForeground); ++ ++ #undef ADD_COLOR ++ ++ return colors; ++} ++ ++std::string ThemeColorsGetFunction::ColorToHexString(SkColor color) { ++ return base::StringPrintf("#%02X%02X%02X", ++ SkColorGetR(color), ++ SkColorGetG(color), ++ SkColorGetB(color)); ++} ++ ++const ui::ColorProvider* ThemeColorsGetFunction::GetColorProvider() { ++ Profile* profile = Profile::FromBrowserContext(browser_context()); ++ if (!profile) { ++ return nullptr; ++ } ++ ++ Browser* browser = chrome::FindBrowserWithProfile(profile); ++ if (!browser || !browser->window()) { ++ return nullptr; ++ } ++ ++ return browser->window()->GetColorProvider(); ++} ++ ++} // namespace extensions +diff --git a/chrome/browser/extensions/api/theme_colors/theme_colors_api.h b/chrome/browser/extensions/api/theme_colors/theme_colors_api.h +new file mode 100644 +index 0000000000000..a4374a3ce94c2 +--- /dev/null ++++ b/chrome/browser/extensions/api/theme_colors/theme_colors_api.h +@@ -0,0 +1,43 @@ ++// Copyright 2024 The Chromium Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef CHROME_BROWSER_EXTENSIONS_API_THEME_COLORS_THEME_COLORS_API_H_ ++#define CHROME_BROWSER_EXTENSIONS_API_THEME_COLORS_THEME_COLORS_API_H_ ++ ++#include "base/values.h" ++#include "extensions/browser/extension_function.h" ++#include "third_party/skia/include/core/SkColor.h" ++#include "ui/color/color_id.h" ++ ++namespace ui { ++class ColorProvider; ++} ++ ++namespace extensions { ++ ++// Implementation of the chrome.themeColors.get API. ++class ThemeColorsGetFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("themeColors.get", THEMECOLORS_GET) ++ ++ protected: ++ ~ThemeColorsGetFunction() override; ++ ++ // ExtensionFunction: ++ ResponseAction Run() override; ++ ++ private: ++ // Gets all theme colors from the ColorProvider ++ base::Value::Dict GetAllThemeColors(const ui::ColorProvider* provider); ++ ++ // Converts SkColor to hex string (e.g., 0xFFAABBCC -> "#AABBCC") ++ std::string ColorToHexString(SkColor color); ++ ++ // Gets the ColorProvider for the current browser context ++ const ui::ColorProvider* GetColorProvider(); ++}; ++ ++} // namespace extensions ++ ++#endif // CHROME_BROWSER_EXTENSIONS_API_THEME_COLORS_THEME_COLORS_API_H_ +diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json +index d67338647ca4c..71ba2aa165131 100644 +--- a/chrome/common/extensions/api/_api_features.json ++++ b/chrome/common/extensions/api/_api_features.json +@@ -1125,5 +1125,10 @@ + "wmDesksPrivate": { + "dependencies": ["permission:wmDesksPrivate"], + "contexts": ["privileged_extension"] ++ }, ++ "themeColors": { ++ "channel": "stable", ++ "extension_types": ["extension", "platform_app", "legacy_packaged_app"], ++ "contexts": ["privileged_extension"] + } + } +diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni +index 3e30dd60fac8a..7ea40891ccbc8 100644 +--- a/chrome/common/extensions/api/api_sources.gni ++++ b/chrome/common/extensions/api/api_sources.gni +@@ -35,6 +35,7 @@ schema_sources_ = [ + "scripting.idl", + "tab_capture.idl", + "tabs.json", ++ "theme_colors.json", + "web_authentication_proxy.webidl", + "web_navigation.json", + +diff --git a/chrome/common/extensions/api/theme_colors.json b/chrome/common/extensions/api/theme_colors.json +new file mode 100644 +index 0000000000000..bb5339f4b2049 +--- /dev/null ++++ b/chrome/common/extensions/api/theme_colors.json +@@ -0,0 +1,67 @@ ++// Copyright 2024 The Chromium Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++[ ++ { ++ "namespace": "themeColors", ++ "description": "Use the chrome.themeColors API to access Chrome's Material Design 3 theme colors. All colors automatically update when the theme changes (light/dark mode).", ++ "unprivileged": true, ++ "types": [ ++ { ++ "id": "ThemeColors", ++ "type": "object", ++ "description": "Object containing all available theme colors as hex strings (e.g., '#FF5733'). Includes both reference colors (kColorRef*) for Material 3 tonal palettes and system colors (kColorSys*) for semantic meanings.", ++ "properties": {}, ++ "additionalProperties": { ++ "type": "string", ++ "description": "Color value in hex format" ++ } ++ }, ++ { ++ "id": "ColorChangeInfo", ++ "type": "object", ++ "description": "Information about theme color changes", ++ "properties": { ++ "colors": { ++ "$ref": "ThemeColors", ++ "description": "The new theme colors after the change" ++ } ++ } ++ } ++ ], ++ "functions": [ ++ { ++ "name": "get", ++ "type": "function", ++ "description": "Gets all theme colors for the current theme (light or dark mode).", ++ "parameters": [], ++ "returns_async": { ++ "name": "callback", ++ "description": "Called with the theme colors", ++ "parameters": [ ++ { ++ "name": "colors", ++ "$ref": "ThemeColors", ++ "description": "Object containing all theme colors with color ID names as keys (e.g., colors.kColorRefPrimary90, colors.kColorSysTonalContainer)" ++ } ++ ] ++ } ++ } ++ ], ++ "events": [ ++ { ++ "name": "onChanged", ++ "type": "function", ++ "description": "Fired when the theme colors change (e.g., switching between light and dark mode).", ++ "parameters": [ ++ { ++ "name": "changeInfo", ++ "$ref": "ColorChangeInfo", ++ "description": "Information about the color changes" ++ } ++ ] ++ } ++ ] ++ } ++] +diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h +index 5b19cff05b9c3..4dbc2097d565a 100644 +--- a/extensions/browser/extension_function_histogram_value.h ++++ b/extensions/browser/extension_function_histogram_value.h +@@ -2013,6 +2013,7 @@ enum HistogramValue { + ACCESSIBILITY_PRIVATE_ENABLESPOKENFEEDBACKMV3KEYHANDLING = 1950, + AUTOFILLPRIVATE_GETWALLETABLEPASSDETECTIONOPTINSTATUS = 1951, + AUTOFILLPRIVATE_SETWALLETABLEPASSDETECTIONOPTINSTATUS = 1952, ++ THEMECOLORS_GET = 1953, + // Last entry: Add new entries above, then run: + // tools/metrics/histograms/update_extension_histograms.py + ENUM_BOUNDARY diff --git a/chromium/patches/settings_ui_changes.patch b/chromium/patches/ui/settings_ui_changes.patch similarity index 97% rename from chromium/patches/settings_ui_changes.patch rename to chromium/patches/ui/settings_ui_changes.patch index 6bd72a0..fe1e092 100644 --- a/chromium/patches/settings_ui_changes.patch +++ b/chromium/patches/ui/settings_ui_changes.patch @@ -24,9 +24,8 @@ index f5659b08ca0ed..9e3df4e5858d3 100644 + + About OpenBrowser -- + - Get help with Chromium -+ + Get help with OpenBrowser @@ -170,7 +169,7 @@ index f5659b08ca0ed..9e3df4e5858d3 100644 -@@ -138,347 +138,347 @@ Chromium understands forms better and can autofill them faster for you. This set +@@ -138,342 +138,342 @@ Chromium understands forms better and can autofill them faster for you. This set @@ -455,19 +454,13 @@ index f5659b08ca0ed..9e3df4e5858d3 100644 + OpenBrowser data in your account -- Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the Chromium data in your Google Account. Payment methods and addresses from Google Pay won’t be encrypted. Browsing history from Chromium won’t sync. -+ Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the OpenBrowser data in your Google Account. Payment methods and addresses from Google Pay won’t be encrypted. Browsing history from OpenBrowser won’t sync. +- Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the Chromium data in your Google Account. Addresses and any data saved in Google Wallet won’t be encrypted by your passphrase. Browsing history from Chromium won’t sync. ++ Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the OpenBrowser data in your Google Account. Addresses and any data saved in Google Wallet won’t be encrypted by your passphrase. Browsing history from OpenBrowser won’t sync. - Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you’ll need to <a href="$1" target="_blank"><a href="$1" target="_blank">delete the Chromium data in your account</a></a>. + Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you’ll need to <a href="$1" target="_blank"><a href="$1" target="_blank">delete the OpenBrowser data in your account</a></a>. - - -- Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the Chromium data in your Google Account. Addresses and any data saved in Google Wallet won’t be encrypted by your passphrase. Browsing history from Chromium won’t sync. -+ Use your <a href="$1" target="_blank"><a href="$1" target="_blank">own passphrase</a></a> to encrypt all the OpenBrowser data in your Google Account. Addresses and any data saved in Google Wallet won’t be encrypted by your passphrase. Browsing history from OpenBrowser won’t sync. - - - If you forgot your passphrase or want to change this setting, <a href="$1" target="_blank"><a href="$1" target="_blank">delete the Chromium data in your account</a></a> + If you forgot your passphrase or want to change this setting, <a href="$1" target="_blank"><a href="$1" target="_blank">delete the OpenBrowser data in your account</a></a> @@ -577,14 +570,12 @@ index f5659b08ca0ed..9e3df4e5858d3 100644 + OpenBrowser is up to date -- + - Go to About Chromium page -+ + Go to About OpenBrowser page -- + - Relaunch Chromium -+ + Relaunch OpenBrowser @@ -634,7 +625,7 @@ diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 7edfde1f4fd6c..e72339448cda0 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp -@@ -340,7 +340,7 @@ +@@ -331,7 +331,7 @@ Settings @@ -643,7 +634,7 @@ index 7edfde1f4fd6c..e72339448cda0 100644 Subpage button -@@ -759,7 +759,7 @@ +@@ -750,7 +750,7 @@ Are you sure you want to delete this passkey? @@ -652,7 +643,7 @@ index 7edfde1f4fd6c..e72339448cda0 100644 Can't delete passkey -@@ -1756,7 +1756,7 @@ +@@ -1747,7 +1747,7 @@ Passwords @@ -661,7 +652,7 @@ index 7edfde1f4fd6c..e72339448cda0 100644 Safe Browsing is on and protecting you from harmful sites and downloads -@@ -3644,8 +3644,8 @@ +@@ -3635,8 +3635,8 @@ @@ -672,7 +663,7 @@ index 7edfde1f4fd6c..e72339448cda0 100644 Google Profile photo -@@ -3654,7 +3654,7 @@ +@@ -3645,7 +3645,7 @@ Sign in diff --git a/patches/ui/theme_and_ui_changes.patch b/chromium/patches/ui/ui-layout-changes.patch similarity index 50% rename from patches/ui/theme_and_ui_changes.patch rename to chromium/patches/ui/ui-layout-changes.patch index 48661e8..7edf544 100644 --- a/patches/ui/theme_and_ui_changes.patch +++ b/chromium/patches/ui/ui-layout-changes.patch @@ -1,276 +1,3 @@ -diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h -index 59296a7cb076a..c349c59837fe9 100644 ---- a/chrome/browser/ui/color/chrome_color_id.h -+++ b/chrome/browser/ui/color/chrome_color_id.h -@@ -657,6 +657,7 @@ - E_CPONLY(kColorSearchboxResultsForeground) \ - E_CPONLY(kColorSearchboxResultsForegroundDimmed) \ - E_CPONLY(kColorSearchboxResultsIcon) \ -+ E_CPONLY(kColorSearchboxResultsIconContainerBackground) \ - E_CPONLY(kColorSearchboxResultsIconFocusedOutline) \ - E_CPONLY(kColorSearchboxResultsIconSelected) \ - E_CPONLY(kColorSearchboxResultsUrl) \ -diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc -index d6f02fceb7ee8..9446c65b4d2cf 100644 ---- a/chrome/browser/ui/color/chrome_color_mixer.cc -+++ b/chrome/browser/ui/color/chrome_color_mixer.cc -@@ -192,9 +192,9 @@ void AddChromeColorMixer(ui::ColorProvider* provider, - mixer[kColorExtensionsMenuContainerBackground] = {ui::kColorSysSurface3}; - mixer[kColorFeatureFirstRunInfoContainerBackground] = {ui::kColorSysSurface3}; - mixer[kColorFeatureFirstRunIconColor] = {ui::kColorSysOnSurfaceSubtle}; -- mixer[kColorFeaturePromoBubbleBackground] = {gfx::kGoogleBlue700}; -+ mixer[kColorFeaturePromoBubbleBackground] = {dark_mode ? SK_ColorWHITE : SK_ColorBLACK}; - mixer[kColorFeaturePromoBubbleButtonBorder] = {gfx::kGoogleGrey300}; -- mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {gfx::kGoogleBlue300}; -+ mixer[kColorFeaturePromoBubbleCloseButtonInkDrop] = {dark_mode ? SK_ColorBLACK : SK_ColorWHITE}; - mixer[kColorFeaturePromoBubbleDefaultButtonBackground] = { - kColorFeaturePromoBubbleForeground}; - mixer[kColorFeaturePromoBubbleDefaultButtonForeground] = { -diff --git a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc -index b2b1a40d80524..18cf4a075b8f2 100644 ---- a/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc -+++ b/chrome/browser/ui/color/material_new_tab_page_color_mixer.cc -@@ -53,7 +53,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, - ui::kColorSysStateHoverOnSubtle}; - mixer[kColorNewTabPageButtonForeground] = {ui::kColorSysOnTonalContainer}; - -- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; -+ mixer[kColorComposeboxBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(SK_ColorWHITE)}; - mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; - mixer[kColorComposeboxFont] = { - dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) -@@ -103,8 +105,9 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, - : SkColorSetRGB(0xAD, 0xAF, 0xB8)}; - mixer[kColorComposeboxFileChipBackground] = {kColorSysSurface3_Light}; - mixer[kColorComposeboxFileChipFaviconBackground] = {kColorSysSurface_Light}; -- mixer[kColorComposeboxFileChipText] = { -- SkColorSetRGB(0x1F, 0x1F, 0x1F)}; -+ mixer[kColorComposeboxFileChipText] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ : SkColorSetRGB(0x1F, 0x1F, 0x1F)}; - mixer[kColorComposeboxPdfChipIcon] = { - dark_mode ? SkColorSetRGB(0xAD, 0xAF, 0xB8) - : SkColorSetRGB(0x56, 0x59, 0x5E)}; -@@ -219,12 +222,20 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, - ui::kColorSysOnPrimary}; - if (base::FeatureList::IsEnabled(ntp_features::kRealboxCr23Theming)) { - // Steady state theme colors. -- mixer[kColorSearchboxBackground] = {kColorToolbarBackgroundSubtleEmphasis}; -+ mixer[kColorSearchboxBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(kColorToolbarBackgroundSubtleEmphasis)}; -+ mixer[kColorSearchboxPlaceholder] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(kColorOmniboxTextDimmed)}; -+ mixer[kColorSearchboxSearchIconBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(kColorOmniboxResultsIcon)}; -+ mixer[kColorSearchboxLensVoiceIconBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(ui::kColorSysPrimary)}; - mixer[kColorSearchboxBackgroundHovered] = { - kColorToolbarBackgroundSubtleEmphasisHovered}; -- mixer[kColorSearchboxPlaceholder] = {kColorOmniboxTextDimmed}; -- mixer[kColorSearchboxSearchIconBackground] = {kColorOmniboxResultsIcon}; -- mixer[kColorSearchboxLensVoiceIconBackground] = {ui::kColorSysPrimary}; - mixer[kColorSearchboxSelectionBackground] = { - kColorOmniboxSelectionBackground}; - mixer[kColorSearchboxSelectionForeground] = { -@@ -235,42 +246,56 @@ void AddMaterialNewTabPageColorMixer(ui::ColorProvider* provider, - kColorOmniboxAnswerIconGM3Background}; - mixer[kColorSearchboxAnswerIconForeground] = { - kColorOmniboxAnswerIconGM3Foreground}; -- mixer[kColorSearchboxForeground] = {kColorOmniboxText}; - mixer[kColorSearchboxResultsActionChip] = {ui::kColorSysTonalOutline}; - mixer[kColorSearchboxResultsActionChipIcon] = {ui::kColorSysPrimary}; - mixer[kColorSearchboxResultsActionChipFocusOutline] = { - ui::kColorSysStateFocusRing}; -- mixer[kColorSearchboxResultsBackgroundHovered] = { -- kColorOmniboxResultsBackgroundHovered}; -- mixer[kColorSearchboxResultsButtonHover] = { -- kColorOmniboxResultsButtonInkDropRowHovered}; -- mixer[kColorSearchboxResultsDimSelected] = { -- kColorOmniboxResultsTextDimmedSelected}; - mixer[kColorSearchboxResultsFocusIndicator] = { - kColorOmniboxResultsFocusIndicator}; -- mixer[kColorSearchboxResultsForeground] = {kColorOmniboxText}; -- mixer[kColorSearchboxResultsForegroundDimmed] = {kColorOmniboxTextDimmed}; -- mixer[kColorSearchboxResultsIcon] = {kColorOmniboxResultsIcon}; -- mixer[kColorSearchboxResultsIconSelected] = {kColorOmniboxResultsIcon}; - mixer[kColorSearchboxResultsIconFocusedOutline] = { - kColorOmniboxResultsButtonIconSelected}; -- mixer[kColorSearchboxResultsUrl] = {kColorOmniboxResultsUrl}; -- mixer[kColorSearchboxResultsUrlSelected] = { -- kColorOmniboxResultsUrlSelected}; -+ -+ mixer[kColorSearchboxForeground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ : ui::ColorTransform(kColorOmniboxText)}; -+ mixer[kColorSearchboxResultsBackgroundHovered] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) -+ : ui::ColorTransform(kColorOmniboxResultsBackgroundHovered)}; -+ mixer[kColorSearchboxResultsButtonHover] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysStateHoverOnSubtle) -+ : ui::ColorTransform(kColorOmniboxResultsButtonInkDropRowHovered)}; -+ mixer[kColorSearchboxResultsDimSelected] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(kColorOmniboxResultsTextDimmedSelected)}; -+ mixer[kColorSearchboxResultsForeground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ : ui::ColorTransform(kColorOmniboxText)}; -+ mixer[kColorSearchboxResultsForegroundDimmed] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(kColorOmniboxTextDimmed)}; -+ mixer[kColorSearchboxResultsIcon] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(kColorOmniboxResultsIcon)}; -+ mixer[kColorSearchboxResultsIconContainerBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(SK_ColorWHITE)}; -+ mixer[kColorSearchboxResultsIconSelected] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : ui::ColorTransform(kColorOmniboxResultsIcon)}; -+ mixer[kColorSearchboxResultsUrl] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) -+ : ui::ColorTransform(kColorOmniboxResultsUrl)}; -+ mixer[kColorSearchboxResultsUrlSelected] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) -+ : ui::ColorTransform(kColorOmniboxResultsUrlSelected)}; - mixer[kColorSearchboxShadow] = - ui::SetAlpha(gfx::kGoogleGrey900, - (dark_mode ? /* % opacity */ 0.32 : 0.1) * SK_AlphaOPAQUE); - -- // This determines weather the realbox expanded state background in dark -- // mode will match the omnibox or not. -- if (dark_mode && -- !ntp_features::kNtpRealboxCr23ExpandedStateBgMatchesOmnibox.Get()) { -- mixer[kColorSearchboxResultsBackground] = { -- kColorToolbarBackgroundSubtleEmphasis}; -- } else { -- mixer[kColorSearchboxResultsBackground] = { -- kColorOmniboxResultsBackground}; -- } -+ // Use base container color for searchbox results background in dark mode, omnibox color in light mode -+ mixer[kColorSearchboxResultsBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(kColorOmniboxResultsBackground)}; - } - - /* NewTabFooter */ -diff --git a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc -index 8d99d0d5e526e..0a06f2f6d7a0d 100644 ---- a/chrome/browser/ui/color/material_tab_strip_color_mixer.cc -+++ b/chrome/browser/ui/color/material_tab_strip_color_mixer.cc -@@ -27,8 +27,9 @@ void AddMaterialTabStripColorMixer(ui::ColorProvider* provider, - - // TODO(crbug.com/40883407): Validate final mappings for ChromeRefresh23 - // color. -+ const bool dark_mode = key.color_mode == ui::ColorProviderKey::ColorMode::kDark; - ui::ColorMixer& mixer = provider->AddMixer(); -- mixer[kColorTabBackgroundActiveFrameActive] = {ui::kColorSysBase}; -+ mixer[kColorTabBackgroundActiveFrameActive] = {dark_mode ? ui::kColorSysBaseContainer : ui::kColorSysSurface}; - mixer[kColorTabBackgroundActiveFrameInactive] = { - kColorTabBackgroundActiveFrameActive}; - -diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc -index 558cc275c8847..350f052b92aef 100644 ---- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc -+++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc -@@ -314,7 +314,7 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, - ui::SelectBasedOnDarkInput(kColorNewTabPageAddShortcutBackground, - SK_ColorWHITE, gfx::kGoogleGrey900); - -- mixer[kColorComposeboxBackground] = {SK_ColorWHITE}; -+ mixer[kColorComposeboxBackground] = {dark_mode ? ui::kColorSysBaseContainer : SK_ColorWHITE}; - mixer[kColorComposeboxFileChipSpinner] = {kColorSysPrimary_Light}; - mixer[kColorComposeboxFont] = { - dark_mode ? SkColorSetRGB(0xE6, 0xE8, 0xF0) -@@ -400,15 +400,28 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, - SkColorSetRGB(0xD3, 0xE3, 0xFD)}; - mixer[kColorSearchboxAnswerIconForeground] = { - SkColorSetRGB(0x04, 0x1E, 0x49)}; -- mixer[kColorSearchboxBackground] = {SK_ColorWHITE}; -- mixer[kColorSearchboxBackgroundHovered] = {SK_ColorWHITE}; -+ mixer[kColorSearchboxBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(SK_ColorWHITE)}; -+ mixer[kColorSearchboxBackgroundHovered] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(SK_ColorWHITE)}; -+ mixer[kColorSearchboxForeground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ : ui::ColorTransform(SK_ColorBLACK)}; -+ mixer[kColorSearchboxPlaceholder] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxLensVoiceIconBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxResultsBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(SK_ColorWHITE)}; - mixer[kColorSearchboxBorder] = { - key.contrast_mode == ui::ColorProviderKey::ContrastMode::kHigh - ? kColorLocationBarBorder - : gfx::kGoogleGrey300}; -- mixer[kColorSearchboxForeground] = {SK_ColorBLACK}; -- mixer[kColorSearchboxPlaceholder] = {gfx::kGoogleGrey700}; -- mixer[kColorSearchboxResultsBackground] = {SK_ColorWHITE}; - mixer[kColorSearchboxResultsBackgroundHovered] = - ui::SetAlpha(gfx::kGoogleGrey900, - /* 10% opacity */ 0.1 * SK_AlphaOPAQUE); -@@ -420,16 +433,39 @@ void AddNewTabPageColorMixer(ui::ColorProvider* provider, - SkColorSetRGB(0x0B, 0x57, 0xD0)}; - mixer[kColorSearchboxResultsActionChipFocusOutline] = { - SkColorSetRGB(0x0B, 0x57, 0xD0)}; -- mixer[kColorSearchboxResultsDimSelected] = {gfx::kGoogleGrey700}; -- mixer[kColorSearchboxResultsFocusIndicator] = {gfx::kGoogleBlue600}; -- mixer[kColorSearchboxResultsForeground] = {SK_ColorBLACK}; -- mixer[kColorSearchboxResultsForegroundDimmed] = {gfx::kGoogleGrey700}; -- mixer[kColorSearchboxResultsIconSelected] = {gfx::kGoogleGrey700}; -- mixer[kColorSearchboxResultsUrl] = {gfx::kGoogleBlue700}; -- mixer[kColorSearchboxResultsUrlSelected] = {gfx::kGoogleBlue700}; -- mixer[kColorSearchboxSearchIconBackground] = {gfx::kGoogleGrey700}; -- mixer[kColorSearchboxResultsIcon] = {gfx::kGoogleGrey700}; -- mixer[kColorSearchboxResultsIconFocusedOutline] = {gfx::kGoogleBlue600}; -+ mixer[kColorSearchboxResultsDimSelected] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxResultsFocusIndicator] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) -+ : gfx::kGoogleBlue600}; -+ mixer[kColorSearchboxResultsForeground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurface) -+ : ui::ColorTransform(SK_ColorBLACK)}; -+ mixer[kColorSearchboxResultsForegroundDimmed] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxResultsIconSelected] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxResultsIconContainerBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysBaseContainer) -+ : ui::ColorTransform(SK_ColorWHITE)}; -+ mixer[kColorSearchboxResultsUrl] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) -+ : gfx::kGoogleBlue700}; -+ mixer[kColorSearchboxResultsUrlSelected] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) -+ : gfx::kGoogleBlue700}; -+ mixer[kColorSearchboxSearchIconBackground] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxResultsIcon] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysOnSurfaceSubtle) -+ : gfx::kGoogleGrey700}; -+ mixer[kColorSearchboxResultsIconFocusedOutline] = -+ {dark_mode ? ui::ColorTransform(ui::kColorSysPrimary) -+ : gfx::kGoogleBlue600}; - mixer[kColorSearchboxShadow] = - ui::SetAlpha(gfx::kGoogleGrey900, - (dark_mode ? /* % opacity */ 0.32 : 0.28) * SK_AlphaOPAQUE); diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc index 4e5901f95885b..8617e0e7afe91 100644 --- a/chrome/browser/ui/layout_constants.cc @@ -928,246 +655,6 @@ index 406d9402d41e1..6d2ea1d68430b 100644 // Dummy feature to set param "NtpModulesLoadTimeoutMillisecondsParam". // This is used for an emergency Finch param. Keep indefinitely. -diff --git a/ui/color/core_default_color_mixer.cc b/ui/color/core_default_color_mixer.cc -index 54cb33c7e3f91..41446d2a935c5 100644 ---- a/ui/color/core_default_color_mixer.cc -+++ b/ui/color/core_default_color_mixer.cc -@@ -25,7 +25,7 @@ void AddCoreDefaultColorMixer(ColorProvider* provider, - DVLOG(2) << "Adding CoreDefaultColorMixer to ColorProvider for " - << (dark_mode ? "Dark" : "Light") << " window."; - ColorMixer& mixer = provider->AddMixer(); -- mixer[kColorAccent] = {dark_mode ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600}; -+ mixer[kColorAccent] = {dark_mode ? SK_ColorWHITE : SK_ColorWHITE}; - // 4.5 and 7.0 approximate the default light and dark theme contrasts of - // accent-against-primary-background. - mixer[kColorAccentWithGuaranteedContrastAtopPrimaryBackground] = -diff --git a/ui/color/mac/native_color_mixers_mac.mm b/ui/color/mac/native_color_mixers_mac.mm -index fb2d49fe27f3d..c740e3b5fa995 100644 ---- a/ui/color/mac/native_color_mixers_mac.mm -+++ b/ui/color/mac/native_color_mixers_mac.mm -@@ -99,11 +99,11 @@ void AddNativeUiColorMixer(ColorProvider* provider, - - mixer[kColorTableBackgroundAlternate] = {skia::NSSystemColorToSkColor( - NSColor.alternatingContentBackgroundColors[1])}; -- if (!key.user_color.has_value()) { -- mixer[kColorSysStateFocusRing] = PickGoogleColor( -- skia::NSSystemColorToSkColor(NSColor.keyboardFocusIndicatorColor), -- kColorSysBase, color_utils::kMinimumVisibleContrastRatio); - -+ // Override focus ring color: white in dark mode, black in light mode -+ mixer[kColorSysStateFocusRing] = {properties.dark ? SK_ColorWHITE : SK_ColorBLACK}; -+ -+ if (!key.user_color.has_value()) { - const SkColor system_highlight_color = - skia::NSSystemColorToSkColor(NSColor.selectedTextBackgroundColor); - mixer[kColorTextSelectionBackground] = {system_highlight_color}; -diff --git a/ui/color/ref_color_mixer.cc b/ui/color/ref_color_mixer.cc -index 3eb2f1053b895..a57a92344f27a 100644 ---- a/ui/color/ref_color_mixer.cc -+++ b/ui/color/ref_color_mixer.cc -@@ -25,36 +25,36 @@ namespace ui { - void AddBaselinePalette(ColorProvider* provider) { - ColorMixer& mixer = provider->AddMixer(); - mixer[kColorRefPrimary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; -- mixer[kColorRefPrimary10] = {SkColorSetRGB(0x04, 0x1E, 0x49)}; -- mixer[kColorRefPrimary20] = {SkColorSetRGB(0x06, 0x2E, 0x6F)}; -- mixer[kColorRefPrimary25] = {SkColorSetRGB(0x07, 0x38, 0x88)}; -- mixer[kColorRefPrimary30] = {SkColorSetRGB(0x08, 0x42, 0xA0)}; -- mixer[kColorRefPrimary40] = {SkColorSetRGB(0x0B, 0x57, 0xD0)}; -- mixer[kColorRefPrimary50] = {SkColorSetRGB(0x1B, 0x6E, 0xF3)}; -- mixer[kColorRefPrimary60] = {SkColorSetRGB(0x4C, 0x8D, 0xF6)}; -- mixer[kColorRefPrimary70] = {SkColorSetRGB(0x7C, 0xAC, 0xF8)}; -- mixer[kColorRefPrimary80] = {SkColorSetRGB(0xA8, 0xC7, 0xFA)}; -- mixer[kColorRefPrimary90] = {SkColorSetRGB(0xD3, 0xE3, 0xFD)}; -- mixer[kColorRefPrimary95] = {SkColorSetRGB(0xEC, 0xF3, 0xFE)}; -- mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFB, 0xFF)}; -+ mixer[kColorRefPrimary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; -+ mixer[kColorRefPrimary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; -+ mixer[kColorRefPrimary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; -+ mixer[kColorRefPrimary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; -+ mixer[kColorRefPrimary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; -+ mixer[kColorRefPrimary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; -+ mixer[kColorRefPrimary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; -+ mixer[kColorRefPrimary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; -+ mixer[kColorRefPrimary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; -+ mixer[kColorRefPrimary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; -+ mixer[kColorRefPrimary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; -+ mixer[kColorRefPrimary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; - mixer[kColorRefPrimary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; - - mixer[kColorRefSecondary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; -- mixer[kColorRefSecondary10] = {SkColorSetRGB(0x00, 0x1D, 0x35)}; -- mixer[kColorRefSecondary12] = {SkColorSetRGB(0x00, 0x22, 0x38)}; -- mixer[kColorRefSecondary15] = {SkColorSetRGB(0x00, 0x28, 0x45)}; -- mixer[kColorRefSecondary20] = {SkColorSetRGB(0x00, 0x33, 0x55)}; -- mixer[kColorRefSecondary25] = {SkColorSetRGB(0x00, 0x3f, 0x66)}; -- mixer[kColorRefSecondary30] = {SkColorSetRGB(0x00, 0x4A, 0x77)}; -- mixer[kColorRefSecondary35] = {SkColorSetRGB(0x00, 0x57, 0x89)}; -- mixer[kColorRefSecondary40] = {SkColorSetRGB(0x00, 0x63, 0x9B)}; -- mixer[kColorRefSecondary50] = {SkColorSetRGB(0x04, 0x7D, 0xB7)}; -- mixer[kColorRefSecondary60] = {SkColorSetRGB(0x39, 0x98, 0xD3)}; -- mixer[kColorRefSecondary70] = {SkColorSetRGB(0x5A, 0xB3, 0xF0)}; -- mixer[kColorRefSecondary80] = {SkColorSetRGB(0x7F, 0xCF, 0xFF)}; -- mixer[kColorRefSecondary90] = {SkColorSetRGB(0xC2, 0xE7, 0xFF)}; -- mixer[kColorRefSecondary95] = {SkColorSetRGB(0xDF, 0xF3, 0xFF)}; -- mixer[kColorRefSecondary99] = {SkColorSetRGB(0xF7, 0xFC, 0xFF)}; -+ mixer[kColorRefSecondary10] = {SkColorSetRGB(0x1A, 0x1A, 0x1A)}; -+ mixer[kColorRefSecondary12] = {SkColorSetRGB(0x1F, 0x1F, 0x1F)}; -+ mixer[kColorRefSecondary15] = {SkColorSetRGB(0x26, 0x26, 0x26)}; -+ mixer[kColorRefSecondary20] = {SkColorSetRGB(0x33, 0x33, 0x33)}; -+ mixer[kColorRefSecondary25] = {SkColorSetRGB(0x40, 0x40, 0x40)}; -+ mixer[kColorRefSecondary30] = {SkColorSetRGB(0x4D, 0x4D, 0x4D)}; -+ mixer[kColorRefSecondary35] = {SkColorSetRGB(0x59, 0x59, 0x59)}; -+ mixer[kColorRefSecondary40] = {SkColorSetRGB(0x66, 0x66, 0x66)}; -+ mixer[kColorRefSecondary50] = {SkColorSetRGB(0x80, 0x80, 0x80)}; -+ mixer[kColorRefSecondary60] = {SkColorSetRGB(0x99, 0x99, 0x99)}; -+ mixer[kColorRefSecondary70] = {SkColorSetRGB(0xB3, 0xB3, 0xB3)}; -+ mixer[kColorRefSecondary80] = {SkColorSetRGB(0xCC, 0xCC, 0xCC)}; -+ mixer[kColorRefSecondary90] = {SkColorSetRGB(0xE6, 0xE6, 0xE6)}; -+ mixer[kColorRefSecondary95] = {SkColorSetRGB(0xF2, 0xF2, 0xF2)}; -+ mixer[kColorRefSecondary99] = {SkColorSetRGB(0xFA, 0xFA, 0xFA)}; - mixer[kColorRefSecondary100] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)}; - - mixer[kColorRefTertiary0] = {SkColorSetRGB(0x00, 0x00, 0x00)}; -diff --git a/ui/color/sys_color_mixer.cc b/ui/color/sys_color_mixer.cc -index 4745b7f50a28b..6cef161038ae8 100644 ---- a/ui/color/sys_color_mixer.cc -+++ b/ui/color/sys_color_mixer.cc -@@ -31,6 +31,8 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, - : kColorRefSecondary30}; - mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefPrimary30 - : kColorRefPrimary90}; -+ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefPrimary90 -+ : kColorRefPrimary10}; - mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefPrimary10 - : kColorRefPrimary90}; - mixer[kColorSysNeutralContainer] = {dark_mode ? kColorRefNeutralVariant15 -@@ -39,18 +41,18 @@ void AddThemedSysColorOverrides(ColorMixer& mixer, - : kColorRefPrimary90}; - - // Chrome surfaces. -- mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary25 -+ mixer[kColorSysBase] = {dark_mode ? kColorRefSecondary10 - : kColorRefNeutral98}; -- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary15 -+ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefSecondary25 - : kColorSysSurface4}; - mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefSecondary25 - : kColorRefNeutral98}; - -- mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary12 -+ mixer[kColorSysHeader] = {dark_mode ? kColorRefSecondary10 - : kColorRefSecondary90}; - mixer[kColorSysHeaderContainer] = {dark_mode ? kColorRefSecondary25 - : kColorRefPrimary95}; -- mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral25 -+ mixer[kColorSysHeaderContainerInactive] = {dark_mode ? kColorRefNeutral10 - : kColorRefNeutral99}; - mixer[kColorSysOnHeaderDivider] = {dark_mode ? kColorRefSecondary25 - : kColorRefPrimary80}; -@@ -78,12 +80,12 @@ void AddGrayscaleSysColorOverrides(ColorMixer& mixer, - - // General - mixer[kColorSysOnSurfacePrimary] = {dark_mode ? kColorRefNeutral90 -- : kColorRefNeutral10}; -- mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 -- : kColorRefNeutral90}; -+ : kColorRefNeutral10}; -+mixer[kColorSysDivider] = {dark_mode ? kColorRefNeutral40 -+: kColorRefNeutral90}; - - // Chrome surfaces. -- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 -+ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 - : kColorRefNeutral90}; - mixer[kColorSysHeaderInactive] = { - dark_mode ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) -@@ -116,24 +118,24 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { - ColorMixer& mixer = provider->AddMixer(); - - // Primary. -- mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary80 -- : kColorRefPrimary40}; -- mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary20 -- : kColorRefPrimary100}; -- mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary30 -- : kColorRefPrimary90}; -- mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary90 -- : kColorRefPrimary10}; -+ mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary90 -+ : kColorRefPrimary10}; -+ mixer[kColorSysOnPrimary] = {dark_mode ? kColorRefPrimary10 -+ : kColorRefPrimary90}; -+ mixer[kColorSysPrimaryContainer] = {dark_mode ? kColorRefPrimary90 -+ : kColorRefPrimary10}; -+ mixer[kColorSysOnPrimaryContainer] = {dark_mode ? kColorRefPrimary10 -+ : kColorRefPrimary90}; - - // Secondary. -- mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary80 -- : kColorRefSecondary40}; -- mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary20 -- : kColorRefSecondary100}; -- mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary30 -- : kColorRefSecondary90}; -- mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary90 -- : kColorRefSecondary10}; -+ mixer[kColorSysSecondary] = {dark_mode ? kColorRefSecondary90 -+ : kColorRefSecondary10}; -+ mixer[kColorSysOnSecondary] = {dark_mode ? kColorRefSecondary10 -+ : kColorRefSecondary90}; -+ mixer[kColorSysSecondaryContainer] = {dark_mode ? kColorRefSecondary90 -+ : kColorRefSecondary10}; -+ mixer[kColorSysOnSecondaryContainer] = {dark_mode ? kColorRefSecondary10 -+ : kColorRefSecondary90}; - // Tertiary. - mixer[kColorSysTertiary] = {dark_mode ? kColorRefTertiary80 - : kColorRefTertiary40}; -@@ -179,8 +181,8 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { - mixer[kColorSysSurface] = {dark_mode ? kColorRefNeutral10 - : kColorRefNeutral100}; - mixer[kColorSysSurfaceNumberedForeground] = { -- dark_mode ? SkColorSetRGB(0xD1, 0xE1, 0xFF) -- : SkColorSetRGB(0x69, 0x91, 0xD6)}; -+ dark_mode ? kColorRefNeutral90 -+ : kColorRefNeutral10}; - mixer[kColorSysSurface1] = AlphaBlend({kColorSysSurfaceNumberedForeground}, - {kColorSysSurface}, 0x0C); - mixer[kColorSysSurface2] = AlphaBlend({kColorSysSurfaceNumberedForeground}, -@@ -202,10 +204,10 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { - mixer[kColorSysOnSurfacePrimaryInactive] = {dark_mode ? kColorRefNeutral90 - : kColorRefNeutral10}; - -- mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary30 -- : kColorRefPrimary90}; -- mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary90 -- : kColorRefPrimary10}; -+ mixer[kColorSysTonalContainer] = {dark_mode ? kColorRefSecondary100 -+ : kColorRefPrimary0}; -+ mixer[kColorSysOnTonalContainer] = {dark_mode ? kColorRefSecondary0 -+ : kColorRefPrimary100}; - mixer[kColorSysBaseTonalContainer] = {dark_mode ? kColorRefSecondary10 - : kColorRefPrimary90}; - mixer[kColorSysOnBaseTonalContainer] = {dark_mode ? kColorRefSecondary90 -@@ -220,14 +222,13 @@ void AddSysColorMixer(ColorProvider* provider, const ColorProviderKey& key) { - : kColorRefPrimary90}; - - // Chrome surfaces. -- mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral25 : kColorRefNeutral100}; -- mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral15 -- : kColorSysSurface4}; -+ mixer[kColorSysBase] = {dark_mode ? kColorRefNeutral10 : kColorRefNeutral100}; -+ mixer[kColorSysBaseContainer] = {dark_mode ? kColorRefNeutral25 : kColorSysSurface4}; - mixer[kColorSysBaseContainerElevated] = {dark_mode ? kColorRefNeutral25 - : kColorRefNeutral100}; - -- mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral12 -- : kColorRefPrimary90}; -+ mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 -+ : kColorRefNeutral90}; - mixer[kColorSysHeaderInactive] = { - dark_mode - ? AlphaBlend({kColorSysHeader}, {kColorRefNeutral25}, 0x99) diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h index cd70752a23e34..6725f520d89c2 100644 --- a/ui/views/controls/menu/menu_item_view.h @@ -1207,44 +694,3 @@ index 34e70f33711a1..dc4fdb93e0fa3 100644 } :host([compose-button-enabled][searchbox-lens-search-enabled_]) { -diff --git a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts -index 6c77613866851..8c2a9b66df274 100644 ---- a/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts -+++ b/ui/webui/resources/cr_components/theme_color_picker/color_utils.ts -@@ -29,26 +29,26 @@ export const DARK_DEFAULT_COLOR: Color = { - }; - - export const LIGHT_BASELINE_BLUE_COLOR: Color = { -- background: {value: 0xff0b57d0}, -- foreground: {value: 0xffd3e3fd}, -- base: {value: 0xffc7c7c7}, -+ background: {value: 0xff000000}, -+ foreground: {value: 0xffffffff}, -+ base: {value: 0xff606060}, - }; - - export const DARK_BASELINE_BLUE_COLOR: Color = { -- background: {value: 0xffa8c7fa}, -- foreground: {value: 0xff0842a0}, -+ background: {value: 0xffffffff}, -+ foreground: {value: 0xff000000}, - base: {value: 0xff757575}, - }; - - export const LIGHT_BASELINE_GREY_COLOR: Color = { -- background: {value: 0xff0b57d0}, -- foreground: {value: 0xffe3e3e3}, -- base: {value: 0xffc7c7c7}, -+ background: {value: 0xff000000}, -+ foreground: {value: 0xffffffff}, -+ base: {value: 0xff606060}, - }; - - export const DARK_BASELINE_GREY_COLOR: Color = { -- background: {value: 0xffa8c7fa}, -- foreground: {value: 0xff474747}, -+ background: {value: 0xffffffff}, -+ foreground: {value: 0xff000000}, - base: {value: 0xff757575}, - }; - diff --git a/chromium/patches/ui/updated-tab-radius.patch b/chromium/patches/ui/updated-tab-radius.patch new file mode 100644 index 0000000..128e7dd --- /dev/null +++ b/chromium/patches/ui/updated-tab-radius.patch @@ -0,0 +1,18 @@ +diff --git a/chrome/browser/ui/tabs/tab_style.cc b/chrome/browser/ui/tabs/tab_style.cc +index a3894efb96e6a..8fc782af616c1 100644 +--- a/chrome/browser/ui/tabs/tab_style.cc ++++ b/chrome/browser/ui/tabs/tab_style.cc +@@ -104,11 +104,11 @@ int TabStyle::GetMinimumInactiveWidth() const { + } + + int TabStyle::GetTopCornerRadius() const { +- return 10; ++ return 4; + } + + int TabStyle::GetBottomCornerRadius() const { +- return 12; ++ return 4; + } + + int TabStyle::GetTabOverlap() const { diff --git a/scripts/apply_branding_assets.sh b/chromium/scripts/apply_branding_assets.sh similarity index 88% rename from scripts/apply_branding_assets.sh rename to chromium/scripts/apply_branding_assets.sh index 64bdeab..5e99bfd 100755 --- a/scripts/apply_branding_assets.sh +++ b/chromium/scripts/apply_branding_assets.sh @@ -6,34 +6,35 @@ set -e # Exit on error -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -OPENBROWSER_ROOT="$(dirname "$SCRIPT_DIR")" -CHROMIUM_SRC="${CHROMIUM_SRC:-$OPENBROWSER_ROOT/../chromium/src}" +SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OB_CHROMIUM_DIR="$(dirname "$SCRIPTS_DIR")" +OB_ROOT="$(dirname "$OB_CHROMIUM_DIR")" +CHROMIUM_SOURCE_DIR="${CHROMIUM_SRC:-$OB_ROOT/../chromium/src}" -ASSETS_DIR="$OPENBROWSER_ROOT/branding_assets" +BRANDING_ASSETS_DIR="$OB_ROOT/branding_assets" echo "=========================================" echo "Applying OpenBrowser Branding Assets" echo "=========================================" -echo "Assets source: $ASSETS_DIR" -echo "Chromium source: $CHROMIUM_SRC" +echo "Assets source: $BRANDING_ASSETS_DIR" +echo "Chromium source: $CHROMIUM_SOURCE_DIR" echo "" -if [ ! -d "$CHROMIUM_SRC" ]; then - echo "ERROR: Chromium source directory not found at $CHROMIUM_SRC" +if [ ! -d "$CHROMIUM_SOURCE_DIR" ]; then + echo "ERROR: Chromium source directory not found at $CHROMIUM_SOURCE_DIR" echo "Set CHROMIUM_SRC environment variable or run from correct location" exit 1 fi -if [ ! -d "$ASSETS_DIR" ]; then - echo "ERROR: Branding assets directory not found at $ASSETS_DIR" +if [ ! -d "$BRANDING_ASSETS_DIR" ]; then + echo "ERROR: Branding assets directory not found at $BRANDING_ASSETS_DIR" exit 1 fi # Function to copy asset with verification copy_asset() { - local src="$ASSETS_DIR/$1" - local dest="$CHROMIUM_SRC/$2" + local src="$BRANDING_ASSETS_DIR/$1" + local dest="$CHROMIUM_SOURCE_DIR/$2" if [ ! -f "$src" ]; then echo "⚠️ WARNING: Source file not found: $src" diff --git a/chromium/scripts/apply_patches.sh b/chromium/scripts/apply_patches.sh index dd3d1f9..1c57fbb 100755 --- a/chromium/scripts/apply_patches.sh +++ b/chromium/scripts/apply_patches.sh @@ -1,8 +1,9 @@ #!/bin/bash -# OpenBrowser Patch Application Script -# Usage: ./apply_patches.sh -set -e +# OpenBrowser Patches Application Script +# Applies patches listed in patches.list file in order + +set -e # Exit on error # Colors for output RED='\033[0;31m' @@ -11,155 +12,110 @@ YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color -# Check arguments -if [ $# -ne 2 ]; then - echo -e "${RED}Usage: $0 ${NC}" - echo "" - echo "Example:" - echo " $0 ./patches ../chromium/src" - exit 1 -fi - -PATCHES_DIR="$1" -SOURCE_DIR="$2" +# Paths +SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OB_CHROMIUM_DIR="$(dirname "$SCRIPTS_DIR")" +OB_ROOT="$(dirname "$OB_CHROMIUM_DIR")" +PATCHES_LIST_FILE="$OB_CHROMIUM_DIR/config/patches.list" +CHROMIUM_SOURCE_DIR="$OB_ROOT/../chromium/src" -# Convert to absolute paths -PATCHES_DIR="$(cd "$PATCHES_DIR" 2>/dev/null && pwd)" || { - echo -e "${RED}Error: Patches directory not found: $1${NC}" +# Check if patches.list exists +if [ ! -f "$PATCHES_LIST_FILE" ]; then + echo -e "${RED}❌ Error: patches.list not found at $PATCHES_LIST_FILE${NC}" exit 1 -} +fi -SOURCE_DIR="$(cd "$SOURCE_DIR" 2>/dev/null && pwd)" || { - echo -e "${RED}Error: Source directory not found: $2${NC}" +# Check if chromium src directory exists +if [ ! -d "$CHROMIUM_SOURCE_DIR" ]; then + echo -e "${RED}❌ Error: Chromium source directory not found at $CHROMIUM_SOURCE_DIR${NC}" exit 1 -} +fi -echo -e "${BLUE}========================================${NC}" -echo -e "${BLUE}OpenBrowser Patch Application Script${NC}" -echo -e "${BLUE}========================================${NC}" +echo "=========================================" +echo "OpenBrowser Patches Application" +echo "=========================================" echo "" -echo -e "Patches Directory: ${GREEN}$PATCHES_DIR${NC}" -echo -e "Source Directory: ${GREEN}$SOURCE_DIR${NC}" +echo "Patches list: $PATCHES_LIST_FILE" +echo "Chromium src: $CHROMIUM_SOURCE_DIR" echo "" -# Find all patch files and sort them -mapfile -t PATCH_FILES < <(find "$PATCHES_DIR" -name "*.patch" -type f | sort) - -if [ ${#PATCH_FILES[@]} -eq 0 ]; then - echo -e "${YELLOW}No patch files found in $PATCHES_DIR${NC}" - exit 0 -fi +# Change to chromium src directory +cd "$CHROMIUM_SOURCE_DIR" -echo -e "${GREEN}Found ${#PATCH_FILES[@]} patch file(s):${NC}" -for i in "${!PATCH_FILES[@]}"; do - RELATIVE_PATH="${PATCH_FILES[$i]#$PATCHES_DIR/}" - echo -e " $((i+1)). $RELATIVE_PATH" -done -echo "" - -# Statistics +# Counters +TOTAL=0 APPLIED=0 SKIPPED=0 FAILED=0 -# Apply patches -for i in "${!PATCH_FILES[@]}"; do - PATCH_FILE="${PATCH_FILES[$i]}" - RELATIVE_PATH="${PATCH_FILE#$PATCHES_DIR/}" - - echo -e "${BLUE}========================================${NC}" - echo -e "${BLUE}Patch $((i+1))/${#PATCH_FILES[@]}: $RELATIVE_PATH${NC}" - echo -e "${BLUE}========================================${NC}" - - # Ask user what to do - while true; do - echo -e "${YELLOW}Options:${NC}" - echo -e " [a] Apply this patch" - echo -e " [s] Skip this patch" - echo -e " [v] View patch contents" - echo -e " [q] Quit (abort remaining patches)" - echo "" - read -p "What would you like to do? [a/s/v/q]: " choice - - case "$choice" in - a|A) - echo -e "${GREEN}Applying patch...${NC}" - cd "$SOURCE_DIR" - - if git apply --check "$PATCH_FILE" 2>/dev/null; then - git apply "$PATCH_FILE" - echo -e "${GREEN}✓ Patch applied successfully!${NC}" - APPLIED=$((APPLIED + 1)) - break - else - echo -e "${RED}✗ Patch failed to apply cleanly${NC}" - echo -e "${YELLOW}Attempting to apply with 3-way merge...${NC}" - - if git apply --3way "$PATCH_FILE" 2>/dev/null; then - echo -e "${GREEN}✓ Patch applied with 3-way merge!${NC}" - APPLIED=$((APPLIED + 1)) - break - else - echo -e "${RED}✗ Patch failed to apply even with 3-way merge${NC}" - FAILED=$((FAILED + 1)) - - echo -e "${YELLOW}Would you like to:${NC}" - echo -e " [c] Continue to next patch" - echo -e " [q] Quit" - read -p "Choice [c/q]: " fail_choice - - if [[ "$fail_choice" == "q" || "$fail_choice" == "Q" ]]; then - echo -e "${RED}Aborting...${NC}" - exit 1 - fi - break - fi - fi - ;; - s|S) - echo -e "${YELLOW}⊘ Skipping patch${NC}" - SKIPPED=$((SKIPPED + 1)) - break - ;; - v|V) - echo -e "${BLUE}--- Patch Contents ---${NC}" - cat "$PATCH_FILE" - echo -e "${BLUE}--- End of Patch ---${NC}" - echo "" - ;; - q|Q) - echo -e "${YELLOW}Quitting...${NC}" - echo "" - echo -e "${BLUE}========================================${NC}" - echo -e "${BLUE}Summary${NC}" - echo -e "${BLUE}========================================${NC}" - echo -e "${GREEN}Applied: $APPLIED${NC}" - echo -e "${YELLOW}Skipped: $SKIPPED${NC}" - echo -e "${RED}Failed: $FAILED${NC}" - echo -e "${BLUE}Aborted: $((${#PATCH_FILES[@]} - APPLIED - SKIPPED - FAILED))${NC}" - exit 0 - ;; - *) - echo -e "${RED}Invalid choice. Please enter a, s, v, or q.${NC}" - ;; - esac - done +# Read patches.list line by line +while IFS= read -r line; do + # Skip comments and empty lines + if [[ "$line" =~ ^#.*$ ]] || [[ -z "$line" ]]; then + continue + fi + + TOTAL=$((TOTAL + 1)) + + # Construct full patch path + PATCH_PATH="$OB_CHROMIUM_DIR/$line" + + # Check if patch file exists + if [ ! -f "$PATCH_PATH" ]; then + echo -e "${RED}❌ [$TOTAL] Patch not found: $line${NC}" + FAILED=$((FAILED + 1)) + continue + fi + + # Get patch filename for display + PATCH_NAME=$(basename "$line") + + echo -e "${BLUE}[$TOTAL] Applying: $PATCH_NAME${NC}" + + # Try to apply the patch + if git apply --check "$PATCH_PATH" 2>/dev/null; then + git apply "$PATCH_PATH" + echo -e "${GREEN} ✅ Applied successfully${NC}" + APPLIED=$((APPLIED + 1)) + else + # Check if already applied + if git apply --reverse --check "$PATCH_PATH" 2>/dev/null; then + echo -e "${YELLOW} ⏭️ Already applied, skipping${NC}" + SKIPPED=$((SKIPPED + 1)) + else + echo -e "${RED} ❌ Failed to apply${NC}" + echo -e "${YELLOW} Running git apply with verbose output:${NC}" + git apply "$PATCH_PATH" 2>&1 | head -20 + FAILED=$((FAILED + 1)) + + # Ask user if they want to continue + read -p "Continue with remaining patches? (y/n) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo -e "${RED}Aborted by user${NC}" + exit 1 + fi + fi + fi + echo "" -done - -# Final summary -echo -e "${BLUE}========================================${NC}" -echo -e "${BLUE}All patches processed!${NC}" -echo -e "${BLUE}========================================${NC}" -echo -e "${GREEN}Applied: $APPLIED${NC}" -echo -e "${YELLOW}Skipped: $SKIPPED${NC}" -echo -e "${RED}Failed: $FAILED${NC}" + +done < "$PATCHES_LIST_FILE" + +# Summary +echo "=========================================" +echo "Summary" +echo "=========================================" +echo -e "Total patches: $TOTAL" +echo -e "${GREEN}Applied: $APPLIED${NC}" +echo -e "${YELLOW}Skipped (already applied): $SKIPPED${NC}" +echo -e "${RED}Failed: $FAILED${NC}" echo "" -if [ $FAILED -gt 0 ]; then - echo -e "${YELLOW}⚠ Some patches failed to apply. Please review the output above.${NC}" - exit 1 -else - echo -e "${GREEN}✓ All patches processed successfully!${NC}" +if [ $FAILED -eq 0 ]; then + echo -e "${GREEN}✅ All patches applied successfully!${NC}" exit 0 +else + echo -e "${RED}⚠️ Some patches failed to apply${NC}" + exit 1 fi diff --git a/chromium/scripts/copy_extension_to_resources.sh b/chromium/scripts/copy_extension_to_resources.sh new file mode 100755 index 0000000..323ddd6 --- /dev/null +++ b/chromium/scripts/copy_extension_to_resources.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# OpenBrowser Extension Copy Script +# This script copies the built chromium extension (dist folder) to the +# Chromium resources directory where it can be loaded as a built-in extension. + +set -e # Exit on error + +SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OB_CHROMIUM_DIR="$(dirname "$SCRIPTS_DIR")" +OB_ROOT="$(dirname "$OB_CHROMIUM_DIR")" +CHROMIUM_SOURCE_DIR="${CHROMIUM_SRC:-$OB_ROOT/../chromium/src}" + +EXTENSION_DIST_DIR="$OB_ROOT/chromium-extension/dist" +EXTENSION_RESOURCES_DIR="$CHROMIUM_SOURCE_DIR/chrome/browser/resources/openbrowser_assistant" + +echo "=========================================" +echo "Copying OpenBrowser Extension to Resources" +echo "=========================================" +echo "Extension source: $EXTENSION_DIST_DIR" +echo "Resources destination: $EXTENSION_RESOURCES_DIR" +echo "" + +if [ ! -d "$CHROMIUM_SOURCE_DIR" ]; then + echo "ERROR: Chromium source directory not found at $CHROMIUM_SOURCE_DIR" + echo "Set CHROMIUM_SRC environment variable or run from correct location" + exit 1 +fi + +if [ ! -d "$EXTENSION_DIST_DIR" ]; then + echo "ERROR: Extension dist directory not found at $EXTENSION_DIST_DIR" + echo "Make sure to build the extension first (e.g., pnpm build)" + exit 1 +fi + +# Remove existing resources if present +if [ -d "$EXTENSION_RESOURCES_DIR" ]; then + echo "🗑️ Removing existing resources at $EXTENSION_RESOURCES_DIR" + rm -rf "$EXTENSION_RESOURCES_DIR" +fi + +# Create destination directory +echo "📁 Creating destination directory..." +mkdir -p "$EXTENSION_RESOURCES_DIR" + +# Copy all files from dist to resources +echo "📋 Copying extension files..." +cp -r "$EXTENSION_DIST_DIR"/* "$EXTENSION_RESOURCES_DIR/" + +# Verify the copy +if [ -f "$EXTENSION_RESOURCES_DIR/manifest.json" ]; then + echo "✅ manifest.json found" +else + echo "⚠️ WARNING: manifest.json not found in destination" + exit 1 +fi + +# Add the key to manifest.json +echo "🔑 Adding extension key to manifest.json..." +MANIFEST_PATH="$EXTENSION_RESOURCES_DIR/manifest.json" +EXTENSION_KEY="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnk6aCCanZ8kXgeZ9DjCSi8m2IhWn+CVGfw9Rm/kGdjGnJrdCCsNi7CwNPqwkC6vW+yRGc1NrBzTTeLzToIeH6p+scCp0zg5iTiOL+xBq1KtyyMGdtH6tb1GvXGud3RwD/GGkmhFsWlRtxzVzyz7NtDBhXlDDDLw/OgDi/DQGYsBfClSSvL1gNToeML+sWiRhBDhUJ+GIRRpOvDCBCXOQXTTwDWiEPFcsmfU2H/nRlWZtfqz8mMPU5ISDTR68dnLc4JhxsegrcQcV9nVxZlUjKXsdR/gdFf3DWCrJQkYwspYyg8MEzqxtRaC/G9RCP88jaBGjf9RFzkB497CpgN5+ywIDAQAB" + +# Use Python to add the key to the manifest.json +python3 -c " +import json +import sys + +try: + with open('$MANIFEST_PATH', 'r') as f: + manifest = json.load(f) + + manifest['key'] = '$EXTENSION_KEY' + + with open('$MANIFEST_PATH', 'w') as f: + json.dump(manifest, f, indent=2) + + print('✅ Extension key added to manifest.json') +except Exception as e: + print(f'❌ ERROR: Failed to add key to manifest.json: {e}', file=sys.stderr) + sys.exit(1) +" + +if [ $? -ne 0 ]; then + echo "⚠️ WARNING: Failed to add key to manifest.json" + exit 1 +fi + +echo "" +echo "=========================================" +echo "✅ Extension copied successfully!" +echo "=========================================" +echo "" +echo "Files copied to: $EXTENSION_RESOURCES_DIR" +echo "" +echo "Next steps:" +echo " 1. Rebuild Chromium to include the updated extension" +echo " 2. The extension will be available as a built-in resource" diff --git a/chromium/scripts/setup_openbrowser.sh b/chromium/scripts/setup_openbrowser.sh new file mode 100755 index 0000000..21db640 --- /dev/null +++ b/chromium/scripts/setup_openbrowser.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# OpenBrowser Complete Setup Script +# Runs all necessary scripts to set up OpenBrowser in Chromium + +set -e # Exit on error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Paths +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +echo -e "${CYAN}" +echo "=========================================" +echo " OpenBrowser Complete Setup" +echo "=========================================" +echo -e "${NC}" +echo "" +echo "This script will:" +echo " 1. Apply all patches" +echo " 2. Copy branding assets" +echo " 3. Copy extension to resources" +echo "" + +# Step 1: Apply patches +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${BLUE}Step 1/3: Applying Patches${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo "" + +if bash "$SCRIPT_DIR/apply_patches.sh"; then + echo -e "${GREEN}✅ Patches applied successfully${NC}" +else + echo -e "${RED}❌ Patch application failed${NC}" + exit 1 +fi + +echo "" +echo "" + +# Step 2: Apply branding assets +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${BLUE}Step 2/3: Applying Branding Assets${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo "" + +if bash "$SCRIPT_DIR/apply_branding_assets.sh"; then + echo -e "${GREEN}✅ Branding assets applied successfully${NC}" +else + echo -e "${RED}❌ Branding assets application failed${NC}" + exit 1 +fi + +echo "" +echo "" + +# Step 3: Copy extension to resources +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${BLUE}Step 3/3: Copying Extension to Resources${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo "" + +if bash "$SCRIPT_DIR/copy_extension_to_resources.sh"; then + echo -e "${GREEN}✅ Extension copied successfully${NC}" +else + echo -e "${RED}❌ Extension copy failed${NC}" + exit 1 +fi + +echo "" +echo "" + +# Final summary +echo -e "${CYAN}" +echo "=========================================" +echo " Setup Complete!" +echo "=========================================" +echo -e "${NC}" +echo "" +echo -e "${GREEN}✅ All steps completed successfully!${NC}" +echo "" +echo "Next steps:" +echo " 1. Build Chromium: autoninja -C out/fast chrome" +echo " 2. Run OpenBrowser: out/fast/Chromium.app/Contents/MacOS/Chromium" +echo "" diff --git a/scripts/apply_patches.sh b/scripts/apply_patches.sh deleted file mode 100755 index 2817a05..0000000 --- a/scripts/apply_patches.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash - -# OpenBrowser Patch Application Script -# This script applies all OpenBrowser patches to the Chromium source tree -# in the correct dependency order. - -set -e # Exit on error - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -OPENBROWSER_ROOT="$(dirname "$SCRIPT_DIR")" -CHROMIUM_SRC="${CHROMIUM_SRC:-$OPENBROWSER_ROOT/../chromium/src}" - -PATCHES_DIR="$OPENBROWSER_ROOT/chromium/patches" - -echo "=========================================" -echo "Applying OpenBrowser Patches" -echo "=========================================" -echo "Patches source: $PATCHES_DIR" -echo "Chromium source: $CHROMIUM_SRC" -echo "" - -if [ ! -d "$CHROMIUM_SRC" ]; then - echo "ERROR: Chromium source directory not found at $CHROMIUM_SRC" - echo "Set CHROMIUM_SRC environment variable or run from correct location" - exit 1 -fi - -if [ ! -d "$PATCHES_DIR" ]; then - echo "ERROR: Patches directory not found at $PATCHES_DIR" - exit 1 -fi - -cd "$CHROMIUM_SRC" - -# Function to apply a single patch -apply_patch() { - local patch_file="$1" - local patch_name="$(basename "$patch_file")" - - echo "----------------------------------------" - echo "Applying: $patch_name" - echo "----------------------------------------" - - if git apply --check "$patch_file" 2>&1; then - git apply "$patch_file" - echo "✅ Successfully applied: $patch_name" - echo "" - return 0 - else - echo "❌ FAILED to apply: $patch_name" - echo "" - echo "Run the following to see details:" - echo " cd $CHROMIUM_SRC" - echo " git apply --check $patch_file" - echo "" - return 1 - fi -} - -# Apply patches in dependency order -# Patch 1: Branding (MUST BE FIRST - has overlaps) -echo "Step 1/4: Applying branding patch..." -if [ -f "$PATCHES_DIR/branding/branding_and_theme.patch" ]; then - apply_patch "$PATCHES_DIR/branding/branding_and_theme.patch" || exit 1 -else - echo "⚠️ WARNING: branding_and_theme.patch not found, skipping" -fi - -# Patch 2: UI Theme Changes (after branding) -echo "Step 2/4: Applying UI theme patch..." -if [ -f "$PATCHES_DIR/ui/theme_and_ui_changes.patch" ]; then - apply_patch "$PATCHES_DIR/ui/theme_and_ui_changes.patch" || exit 1 -else - echo "⚠️ WARNING: theme_and_ui_changes.patch not found, skipping" -fi - -# Patch 3: Settings UI (after branding) -echo "Step 3/4: Applying settings UI patch..." -if [ -f "$PATCHES_DIR/settings_ui_changes.patch" ]; then - apply_patch "$PATCHES_DIR/settings_ui_changes.patch" || exit 1 -else - echo "⚠️ WARNING: settings_ui_changes.patch not found, skipping" -fi - -# Patch 4: URL Branding (independent - can be applied anytime) -echo "Step 4/4: Applying URL branding patch..." -if [ -f "$PATCHES_DIR/branding_url_changes.patch" ]; then - apply_patch "$PATCHES_DIR/branding_url_changes.patch" || exit 1 -else - echo "⚠️ WARNING: branding_url_changes.patch not found, skipping" -fi - -echo "=========================================" -echo "✅ All patches applied successfully!" -echo "=========================================" -echo "" -echo "Next steps:" -echo " 1. Run apply_branding_assets.sh to copy binary assets" -echo " 2. Build Chromium with autoninja -C out/Default chrome" -echo ""