M126 stage 6 and update PATCHES.md

This commit is contained in:
Alexander Frick 2024-07-29 12:09:04 -05:00
parent eb10d33bdc
commit 9afe5f5d19
16 changed files with 993 additions and 212 deletions

View file

@ -15,7 +15,7 @@ Ink > https://chromium.googlesource.com/chromium/src/third_party/+/c4f7a938fcdc7
- Implemented with the args.gn flag "enable_ink = true" Adds PDF annotation features present in CrOS.
MPEG-DASH > https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP
- Implemented with the args.gn flags "enable_hls_sample_aes = true" and "enable_mse_mpeg2ts_stream_parser = true"
- Implemented via the args.gn flags "enable_hls_demuxer = true" and "enable_mse_mpeg2ts_stream_parser = true"
Enable JPEG XL Image File Format by Default Patch
- Made by me.
@ -23,7 +23,13 @@ Enable JPEG XL Image File Format by Default Patch
Enable Live Caption (SODA) on all builds Patch
- Made by me.
V8 Font Rendering Patch > https://github.com/saiarcot895/chromium-ubuntu-build/blob/master/debian/patches/fix-font-rendering.patch
Enable AutoPlay of WebAudio, when AutoPlay is normally disallowed
- Made by me.
Reversion of some Chrome Refresh 2023 UI elements (most notably the restoration of the tab search button to the right side of the tabstrip)
- Made by me.
REMOVED ~~V8 Font Rendering Patch > https://github.com/saiarcot895/chromium-ubuntu-build/blob/master/debian/patches/fix-font-rendering.patch~~
- Fixes font rendering in certain instances.
VAAPI Patch > https://github.com/saiarcot895/chromium-ubuntu-build/blob/master/debian/patches/enable-vaapi-on-linux.diff
@ -63,8 +69,10 @@ Enable Fingerprinting Protection Patch
- Made by me.
Show full URLs by Default Patch > https://github.com/Alex313031/thorium/blob/74219f27911e133483c3ab85c70ba4360ea98423/src/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc#L292
- Made by me.
Disable Privacy Sandbox (previously known as FLOC) Patch > https://github.com/ungoogled-software/ungoogled-chromium/blob/master/patches/core/ungoogled-chromium/disable-privacy-sandbox.patch
- Modified from UnGoogled patch
Disable Google API Key Warning Infobar Patch > https://github.com/Eloston/ungoogled-chromium/blob/master/patches/extra/debian/disable/google-api-warning.patch & https://github.com/Eloston/ungoogled-chromium/blob/master/patches/extra/inox-patchset/0013-disable-missing-key-warning.patch
- Modified by me.
@ -185,7 +193,7 @@ Enable AC3 and EAC3 for HEVC Patch - https://github.com/Muril-o/electron-chromiu
- https://github.com/Alex313031/thorium/commit/a2e49dd2fe00e4c6fa882a41e8a1a27f93bedfff AND
- https://github.com/Alex313031/thorium/commit/7d0b4f045ce0e16ea9edb05a4dc056a1d4583752#diff-09b3d55a8198fc42186bfd6bf5869fe78b8edad6f67e75b78228446f1d7cf66f
Show the Apps button in Bookmarks Bar by Default Patch - Made by me.
Show the Apps button in Bookmarks Bar by Default Patch - Made by me. NOTE: Now only enabled in the legacy builds after M120.
Add autocomplete for chrome://flags > https://github.com/bromite/bromite/blob/master/build/patches/Offer-builtin-autocomplete-for-chrome-flags.patch
@ -224,6 +232,9 @@ Enable Middle Click Autoscroll on ALL Platforms - https://github.com/Alex313031/
Patches to enable truly Portable usage > Disable Encryption and Machine ID
- https://github.com/ungoogled-software/ungoogled-chromium-windows/blob/master/patches/ungoogled-chromium/windows/windows-disable-encryption.patch
- https://github.com/ungoogled-software/ungoogled-chromium-windows/blob/master/patches/ungoogled-chromium/windows/windows-disable-machine-id.patch
> Also added a patch by win32ss from Supermium to allow reversion of a portable profile back to a normal, encrypted one:
- https://github.com/win32ss/supermium/commit/697055c2e65074bf50d30c58e124ddfe293c3f8c AND
- https://github.com/win32ss/supermium/commit/1e2e02118f5f014cb1761f6ae05e86ab4304f924
Android Patches from Bromite:
- https://github.com/bromite/bromite/blob/master/build/patches/do-not-add-suffix-to-package-name.patch

View file

@ -215,6 +215,12 @@
"Disable Machine ID",
"Disables use of a generated machine-specific ID to lock the user data directory to that machine. This is used to enable portable user data directories. Enabled for Thorium Portable.",
kOsDesktop, SINGLE_VALUE_TYPE("disable-machine-id")},
{"revert-from-portable",
"Prevent Data Loss When Changing User Profile Portable State",
"When moving a Thorium user profile from one drive to another (or one system to another), enable this flag before moving the profile directory. It should also be used "
"when migrating a portable profile back to a normal, non-portable profile (i.e. when disabling the `chrome://flags#disable-encryption` and/or the `chrome://flags#disable-machine-id` flags "
"after being previously enabled). This mostly ensures that extensions, extension data, and some other data are not lost during the migration.",
kOsDesktop, SINGLE_VALUE_TYPE("disable-machine-id")},
#if BUILDFLAG(IS_LINUX)
{"password-store",

View file

@ -109,6 +109,7 @@
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_ui_prefs.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window_features.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
@ -123,6 +124,7 @@
#include "chrome/browser/ui/overscroll_pref_manager.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/browser/ui/signin/cookie_clear_on_exit_migration_notice.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/status_bubble.h"
#include "chrome/browser/ui/sync/browser_synced_window_delegate.h"
@ -133,6 +135,7 @@
#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h"
#include "chrome/browser/ui/tabs/tab_enums.h"
#include "chrome/browser/ui/tabs/tab_group.h"
#include "chrome/browser/ui/tabs/tab_group_deletion_dialog_controller.h"
#include "chrome/browser/ui/tabs/tab_group_model.h"
#include "chrome/browser/ui/tabs/tab_menu_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
@ -140,6 +143,7 @@
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/unload_controller.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/contents_web_view.h"
#include "chrome/browser/ui/views/message_box_dialog.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
@ -177,7 +181,6 @@
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/omnibox/browser/location_bar_model.h"
#include "components/omnibox/browser/location_bar_model_impl.h"
#include "components/omnibox/browser/omnibox_prefs.h"
#include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
#include "components/paint_preview/buildflags/buildflags.h"
@ -232,6 +235,7 @@
#include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h"
#include "third_party/blink/public/mojom/frame/frame.mojom.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "third_party/blink/public/mojom/page/draggable_region.mojom.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
#include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
#include "ui/base/l10n/l10n_util.h"
@ -356,6 +360,43 @@ bool IsOnKioskSplashScreen() {
#endif
}
// Returns a pair [last_window, last_window_for_profile] indicating if `browser`
// is the only browser in total and for this profile.
// Ignores browsers that are in the process of closing.
std::pair<bool, bool> IsLastWindow(const Browser& browser) {
bool last_window = true;
bool last_window_for_profile = true;
for (Browser* other_browser : *BrowserList::GetInstance()) {
// Don't count this browser window or any other in the process of closing.
// Window closing may be delayed, and windows that are in the process of
// closing don't count against our totals.
if (other_browser == &browser ||
other_browser->IsAttemptingToCloseBrowser()) {
continue;
}
last_window = false;
if (other_browser->profile() == browser.profile()) {
last_window_for_profile = false;
break;
}
}
return {last_window, last_window_for_profile};
}
// Returns whether the cookie migration notice should be shown: the migration
// is not complete, and this is the last browser window open for this profile.
bool ShouldShowCookieMigrationNoticeForBrowser(const Browser& browser) {
if (!CanShowCookieClearOnExitMigrationNotice(browser)) {
return false;
}
auto [last_window, last_window_for_profile] = IsLastWindow(browser);
return last_window_for_profile;
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
@ -418,6 +459,19 @@ Browser::CreateParams Browser::CreateParams::CreateForAppPopup(
profile, user_gesture);
}
// static
Browser::CreateParams Browser::CreateParams::CreateForPictureInPicture(
const std::string& app_name,
bool trusted_source,
Profile* profile,
bool user_gesture) {
Browser::CreateParams browser_params(Browser::TYPE_PICTURE_IN_PICTURE,
profile, user_gesture);
browser_params.app_name = app_name;
browser_params.trusted_source = trusted_source;
return browser_params;
}
// static
Browser::CreateParams Browser::CreateParams::CreateForDevTools(
Profile* profile) {
@ -448,12 +502,6 @@ Browser::CreationStatus Browser::GetCreationStatusForProfile(Profile* profile) {
return CreationStatus::kOk;
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
// static
const char* Browser::url_elision_extension_id_ =
"jknemblkbdhdcpllfgbfekkdciegfboi";
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
// static
Browser* Browser::Create(const CreateParams& params) {
// If this is failing, a caller is trying to create a browser when creation is
@ -495,12 +543,15 @@ Browser::Browser(const CreateParams& params)
new BrowserContentSettingBubbleModelDelegate(this)),
location_bar_model_delegate_(new BrowserLocationBarModelDelegate(this)),
location_bar_model_(std::make_unique<LocationBarModelImpl>(
location_bar_model_delegate_.get(), content::kMaxURLDisplayChars)),
location_bar_model_delegate_.get(),
content::kMaxURLDisplayChars)),
live_tab_context_(new BrowserLiveTabContext(this)),
synced_window_delegate_(new BrowserSyncedWindowDelegate(this)),
app_controller_(web_app::MaybeCreateAppBrowserController(this)),
bookmark_bar_state_(BookmarkBar::HIDDEN),
command_controller_(new chrome::BrowserCommandController(this)),
tab_group_deletion_dialog_controller_(
std::make_unique<tab_groups::DeletionDialogController>(this)),
window_has_shown_(false),
user_title_(params.user_title),
signin_view_controller_(this),
@ -549,6 +600,12 @@ Browser::Browser(const CreateParams& params)
if (params.skip_window_init_for_testing)
return;
// BrowserWindowFeatures need to be initialized before browser window
// creation, so that the features can be used in creating components
// in browser window.
features_ = BrowserWindowFeatures::CreateBrowserWindowFeatures();
features_->Init(this);
window_ = params.window ? params.window.get()
: CreateBrowserWindow(std::unique_ptr<Browser>(this),
params.user_gesture,
@ -576,25 +633,6 @@ Browser::Browser(const CreateParams& params)
->ListenToFullScreenChanges();
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
// Temporary migration code: if users have the Suspicious Site Reporter
// extension installed, which has the effect of disabling URL elisions in the
// omnibox, set the pref that disables URL elisions. This is so that we can
// eventually deprecate this extension without reverting its users to elided
// URL display.
// TODO(crbug/324934130): remove this code and deprecate the extension in
// ~M125 or so.
if (!profile_->GetPrefs()
->FindPreference(omnibox::kPreventUrlElisionsInOmnibox)
->IsManaged() &&
extensions::ExtensionRegistry::Get(profile_)
->enabled_extensions()
.Contains(url_elision_extension_id_)) {
profile_->GetPrefs()->SetBoolean(omnibox::kPreventUrlElisionsInOmnibox,
true);
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
BrowserList::AddBrowser(this);
}
@ -607,14 +645,17 @@ Browser::~Browser() {
// The tab strip should not have any tabs at this point.
//
// TODO(crbug.com/1407055): This DCHECK doesn't always pass.
// TODO(crbug.com/1434387): convert this to CHECK.
// TODO(crbug.com/40887606): This DCHECK doesn't always pass.
// TODO(crbug.com/40064092): convert this to CHECK.
DCHECK(tab_strip_model_->empty());
// Destroy the BrowserCommandController before removing the browser, so that
// it doesn't act on any notifications that are sent as a result of removing
// the browser.
command_controller_.reset();
// Destroy ExclusiveAccessManager, which depends on `window_` which may be
// destroyed by RemoveBrowser().
exclusive_access_manager_.reset();
BrowserList::RemoveBrowser(this);
// If closing the window is going to trigger a shutdown, then we need to
@ -625,7 +666,8 @@ Browser::~Browser() {
if (!browser_defaults::kBrowserAliveWithNoWindows &&
OkToCloseWithInProgressDownloads(&num_downloads) ==
DownloadCloseType::kBrowserShutdown) {
DownloadCoreService::CancelAllDownloads();
DownloadCoreService::CancelAllDownloads(
DownloadCoreService::CancelDownloadsTrigger::kShutdown);
}
SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this);
@ -660,7 +702,7 @@ Browser::~Browser() {
// Non-primary OffTheRecord profiles should not be destroyed directly by
// Browser (e.g. for offscreen tabs, https://crbug.com/664351).
//
// TODO(crbug.com/1153922): Use ScopedProfileKeepAlive for Incognito too,
// TODO(crbug.com/40159237): Use ScopedProfileKeepAlive for Incognito too,
// instead of separate logic for Incognito and regular profiles.
if (profile_->IsIncognitoProfile() &&
!BrowserList::IsOffTheRecordBrowserInUse(profile_) &&
@ -897,14 +939,31 @@ Browser::WarnBeforeClosingResult Browser::MaybeWarnBeforeClosing(
// before-unload handlers by setting `force_skip_warning_user_on_close_` to
// true or there are no pending downloads we need to prompt about) then
// there's no need to warn.
if (force_skip_warning_user_on_close_ || CanCloseWithInProgressDownloads()) {
if (force_skip_warning_user_on_close_) {
if (CanCloseWithMultipleTabs())
return WarnBeforeClosingResult::kOkToClose;
}
// `CanCloseWithInProgressDownloads()` may trigger a modal dialog.
bool can_close_with_downloads = CanCloseWithInProgressDownloads();
if (can_close_with_downloads &&
!ShouldShowCookieMigrationNoticeForBrowser(*this)) {
return WarnBeforeClosingResult::kOkToClose;
}
// If there is no download warning, show the cookie migration notice now.
// Otherwise, the download warning is being shown. Cookie migration notice
// will be shown after, if needed.
if (can_close_with_downloads) {
ShowCookieClearOnExitMigrationNotice(
*this, base::BindOnce(&Browser::CookieMigrationNoticeResponse,
weak_factory_.GetWeakPtr()));
}
DCHECK(!warn_before_closing_callback_)
<< "Tried to close window during close warning; dialog should be modal.";
warn_before_closing_callback_ = std::move(warn_callback);
return WarnBeforeClosingResult::kDoNotClose;
}
@ -998,6 +1057,21 @@ void Browser::ClearForceShowBookmarkBarFlag(ForceShowBookmarkBarFlag flag) {
UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_FORCE_SHOW);
}
views::WebView* Browser::GetWebView() {
return window_->GetContentsWebView();
}
void Browser::OpenURL(const GURL& gurl, WindowOpenDisposition disposition) {
OpenURL(content::OpenURLParams(gurl, content::Referrer(), disposition,
ui::PAGE_TRANSITION_LINK,
/*is_renderer_initiated=*/false),
/*navigation_handle_callback=*/{});
}
const SessionID& Browser::GetSessionID() {
return session_id_;
}
void Browser::OnWindowClosing() {
if (const auto closing_status = HandleBeforeClose();
closing_status != BrowserClosingStatus::kPermitted) {
@ -1069,23 +1143,11 @@ Browser::DownloadCloseType Browser::OkToCloseWithInProgressDownloads(
// Figure out how many windows are open total, and associated with this
// profile, that are relevant for the ok-to-close decision.
int profile_window_count = 0;
int total_window_count = 0;
for (Browser* browser : *BrowserList::GetInstance()) {
// Don't count this browser window or any other in the process of closing.
// Window closing may be delayed, and windows that are in the process of
// closing don't count against our totals.
if (browser == this || browser->IsAttemptingToCloseBrowser())
continue;
if (browser->profile() == profile())
profile_window_count++;
total_window_count++;
}
auto [last_window, last_window_for_profile] = IsLastWindow(*this);
// If there aren't any other windows, we're at browser shutdown,
// which would cancel all current downloads.
if (total_window_count == 0) {
if (last_window) {
*num_downloads_blocking = total_download_count;
return DownloadCloseType::kBrowserShutdown;
}
@ -1095,7 +1157,7 @@ Browser::DownloadCloseType Browser::OkToCloseWithInProgressDownloads(
// those downloads would be cancelled by our window (-> profile) close.
DownloadCoreService* download_core_service =
DownloadCoreServiceFactory::GetForBrowserContext(profile());
if ((profile_window_count == 0) &&
if (last_window_for_profile &&
(download_core_service->BlockingShutdownCount() > 0) &&
(profile()->IsIncognitoProfile() || profile()->IsGuestSession())) {
*num_downloads_blocking = download_core_service->BlockingShutdownCount();
@ -1241,12 +1303,15 @@ void Browser::UnregisterKeepAlive() {
///////////////////////////////////////////////////////////////////////////////
// Browser, PageNavigator implementation:
WebContents* Browser::OpenURL(const OpenURLParams& params) {
WebContents* Browser::OpenURL(
const OpenURLParams& params,
base::OnceCallback<void(content::NavigationHandle&)>
navigation_handle_callback) {
#if DCHECK_IS_ON()
DCHECK(params.Valid());
#endif
return OpenURLFromTab(nullptr, params);
return OpenURLFromTab(nullptr, params, std::move(navigation_handle_callback));
}
///////////////////////////////////////////////////////////////////////////////
@ -1323,10 +1388,7 @@ void Browser::OnTabGroupChanged(const TabGroupChange& change) {
->visual_data();
const tab_groups::SavedTabGroupKeyedService* const
saved_tab_group_keyed_service =
base::FeatureList::IsEnabled(features::kTabGroupsSave)
? tab_groups::SavedTabGroupServiceFactory::GetForProfile(
profile_)
: nullptr;
tab_groups::SavedTabGroupServiceFactory::GetForProfile(profile_);
std::optional<std::string> saved_guid;
if (saved_tab_group_keyed_service) {
@ -1499,7 +1561,7 @@ void Browser::CreateSmsPrompt(content::RenderFrameHost*,
const std::string& one_time_code,
base::OnceClosure on_confirm,
base::OnceClosure on_cancel) {
// TODO(crbug.com/1015645): implementation left pending deliberately.
// TODO(crbug.com/40103792): implementation left pending deliberately.
std::move(on_confirm).Run();
}
@ -1577,32 +1639,6 @@ void Browser::UpdateInspectedWebContentsIfNecessary(
}
}
std::unique_ptr<content::WebContents> Browser::SwapWebContents(
content::WebContents* old_contents,
std::unique_ptr<content::WebContents> new_contents) {
// Copies the background color and contents of the old WebContents to a new
// one that replaces it on the screen. This allows the new WebContents to
// have something to show before having loaded any contents. As a result, we
// avoid flashing white when navigating from a site with a dark background to
// another site with a dark background.
if (old_contents && new_contents) {
RenderWidgetHostView* old_view =
old_contents->GetPrimaryMainFrame()->GetView();
RenderWidgetHostView* new_view =
new_contents->GetPrimaryMainFrame()->GetView();
if (old_view && new_view)
new_view->TakeFallbackContentFrom(old_view);
}
// Clear the task manager tag. The TabStripModel will associate its own task
// manager tag.
task_manager::WebContentsTags::ClearTag(new_contents.get());
int index = tab_strip_model_->GetIndexOfWebContents(old_contents);
DCHECK_NE(TabStripModel::kNoTab, index);
return tab_strip_model_->ReplaceWebContentsAt(index, std::move(new_contents));
}
bool Browser::ShouldShowStaleContentOnEviction(content::WebContents* source) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
return source == tab_strip_model_->GetActiveWebContents();
@ -1611,10 +1647,9 @@ bool Browser::ShouldShowStaleContentOnEviction(content::WebContents* source) {
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
}
// TODO(crbug.com/1198344): Remove this.
// TODO(crbug.com/40177301): Remove this.
void Browser::MediaWatchTimeChanged(
const content::MediaPlayerWatchTime& watch_time) {
}
const content::MediaPlayerWatchTime& watch_time) {}
bool Browser::IsPointerLocked() const {
return exclusive_access_manager_->pointer_lock_controller()
@ -1644,8 +1679,11 @@ void Browser::OnWindowDidShow() {
///////////////////////////////////////////////////////////////////////////////
// Browser, content::WebContentsDelegate implementation:
WebContents* Browser::OpenURLFromTab(WebContents* source,
const OpenURLParams& params) {
WebContents* Browser::OpenURLFromTab(
WebContents* source,
const OpenURLParams& params,
base::OnceCallback<void(content::NavigationHandle&)>
navigation_handle_callback) {
TRACE_EVENT1("navigation", "Browser::OpenURLFromTab", "source", source);
#if DCHECK_IS_ON()
DCHECK(params.Valid());
@ -1654,7 +1692,8 @@ WebContents* Browser::OpenURLFromTab(WebContents* source,
if (is_type_devtools()) {
DevToolsWindow* window = DevToolsWindow::AsDevToolsWindow(source);
DCHECK(window);
return window->OpenURLFromTab(source, params);
return window->OpenURLFromTab(source, params,
std::move(navigation_handle_callback));
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
@ -1688,7 +1727,12 @@ WebContents* Browser::OpenURLFromTab(WebContents* source,
chrome::ConfigureTabGroupForNavigation(popup_delegate->nav_params());
Navigate(popup_delegate->nav_params());
base::WeakPtr<content::NavigationHandle> navigation_handle =
Navigate(popup_delegate->nav_params());
if (navigation_handle_callback && navigation_handle) {
std::move(navigation_handle_callback).Run(*navigation_handle);
}
content::WebContents* navigated_or_inserted_contents =
popup_delegate->nav_params()->navigated_or_inserted_contents;
@ -1856,19 +1900,22 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
GetStatusBubble()->SetURL(url);
}
void Browser::ContentsMouseEvent(WebContents* source,
bool motion,
bool exited) {
exclusive_access_manager_->OnUserInput();
void Browser::ContentsMouseEvent(WebContents* source, const ui::Event& event) {
const ui::EventType type = event.type();
const bool exited = type == ui::ET_MOUSE_EXITED;
// Disregard synthesized events, and mouse enter and exit, which may occur
// without explicit user input events during window state changes.
if (type != ui::ET_MOUSE_ENTERED && !exited && !event.IsSynthesized()) {
exclusive_access_manager_->OnUserInput();
}
// Mouse motion events update the status bubble, if it exists.
if (!GetStatusBubble() || (!motion && !exited))
return;
if (source == tab_strip_model_->GetActiveWebContents()) {
if (GetStatusBubble() && source == tab_strip_model_->GetActiveWebContents() &&
(type == ui::ET_MOUSE_MOVED || exited)) {
GetStatusBubble()->MouseMoved(exited);
if (exited)
if (exited) {
GetStatusBubble()->SetURL(GURL());
}
}
}
@ -2044,6 +2091,14 @@ bool Browser::ShouldUseInstancedSystemMediaControls() const {
return is_type_app() || is_type_app_popup();
}
void Browser::DraggableRegionsChanged(
const std::vector<blink::mojom::DraggableRegionPtr>& regions,
content::WebContents* contents) {
if (app_controller_) {
app_controller_->DraggableRegionsChanged(regions, contents);
}
}
void Browser::DidFinishNavigation(
content::WebContents* web_contents,
content::NavigationHandle* navigation_handle) {
@ -2107,15 +2162,14 @@ ui::WindowShowState Browser::GetWindowShowState() const {
}
bool Browser::CanEnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
content::RenderFrameHost* requesting_frame) {
// If the tab strip isn't editable then a drag session is in progress, and it
// is not safe to enter fullscreen. https://crbug.com/1315080
if (!tab_strip_model_delegate_->IsTabStripEditable())
return false;
return exclusive_access_manager_->fullscreen_controller()
->CanEnterFullscreenModeForTab(requesting_frame, options.display_id);
->CanEnterFullscreenModeForTab(requesting_frame);
}
void Browser::EnterFullscreenModeForTab(
@ -2473,7 +2527,8 @@ void Browser::FileSelected(const ui::SelectedFileInfo& file_info,
return;
OpenURL(OpenURLParams(url, Referrer(), WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_TYPED, false));
ui::PAGE_TRANSITION_TYPED, false),
/*navigation_handle_callback=*/{});
}
void Browser::FileSelectionCanceled(void* params) {
@ -2515,7 +2570,7 @@ void Browser::OnTabInsertedAt(WebContents* contents, int index) {
// added to it. This is because scheduling the delete can not be undone, and
// proper cleanup is not done if a WebContents is added once delete it
// scheduled (WebContents is leaked, unload handlers aren't checked...).
// TODO(crbug.com/1434387): this should check that `is_delete_scheduled_` is
// TODO(crbug.com/40064092): this should check that `is_delete_scheduled_` is
// false.
DUMP_WILL_BE_CHECK(!is_delete_scheduled_);
@ -2736,7 +2791,7 @@ void Browser::ScheduleUIUpdate(WebContents* source, unsigned changed_flags) {
// WebContents may in some rare cases send updates after they've been detached
// from the tabstrip but before they are deleted, causing a potential crash if
// we proceed. For now bail out.
// TODO(crbug.com/1007379) Figure out a safe way to detach browser delegate
// TODO(crbug.com/40100269) Figure out a safe way to detach browser delegate
// from WebContents when it's removed so this doesn't happen - then put a
// DCHECK back here.
if (tab_strip_model_->GetIndexOfWebContents(source) == TabStripModel::kNoTab)
@ -2846,7 +2901,7 @@ void Browser::ProcessPendingUIUpdates() {
// hidden.
if (flags & content::INVALIDATE_TYPE_TAB) {
UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE);
// TODO(crbug.com/1062235): Ideally, we should simply ask the state to
// TODO(crbug.com/40122780): Ideally, we should simply ask the state to
// update, and doing that in an appropriate and efficient manner.
window()->UpdatePageActionIcon(PageActionIconType::kPwaInstall);
}
@ -3016,8 +3071,15 @@ bool Browser::CanCloseWithMultipleTabs() {
void Browser::InProgressDownloadResponse(bool cancel_downloads) {
if (cancel_downloads) {
cancel_download_confirmation_state_ = RESPONSE_RECEIVED;
std::move(warn_before_closing_callback_)
.Run(WarnBeforeClosingResult::kOkToClose);
if (ShouldShowCookieMigrationNoticeForBrowser(*this)) {
ShowCookieClearOnExitMigrationNotice(
*this, base::BindOnce(&Browser::CookieMigrationNoticeResponse,
weak_factory_.GetWeakPtr()));
} else {
std::move(warn_before_closing_callback_)
.Run(WarnBeforeClosingResult::kOkToClose);
}
return;
}
@ -3049,6 +3111,12 @@ void Browser::MultitabResponse(chrome::MessageBoxResult result) {
.Run(WarnBeforeClosingResult::kDoNotClose);
}
void Browser::CookieMigrationNoticeResponse(bool proceed_closing) {
std::move(warn_before_closing_callback_)
.Run(proceed_closing ? WarnBeforeClosingResult::kOkToClose
: WarnBeforeClosingResult::kDoNotClose);
}
void Browser::FinishWarnBeforeClosing(WarnBeforeClosingResult result) {
switch (result) {
case WarnBeforeClosingResult::kOkToClose:
@ -3187,12 +3255,12 @@ bool Browser::AppBrowserSupportsWindowFeature(WindowFeature feature,
// current page can be shown when browsing a url that is not inside the app.
// Note: Final determination of whether or not the toolbar is shown is made
// by the |AppBrowserController|.
// TODO(crbug.com/992834): Make this control the visibility of Browser
// TODO(crbug.com/40639933): Make this control the visibility of Browser
// Controls more generally.
case FEATURE_TOOLBAR:
return true;
case FEATURE_TITLEBAR:
// TODO(crbug.com/992834): Make this control the visibility of
// TODO(crbug.com/40639933): Make this control the visibility of
// CustomTabBarView.
case FEATURE_LOCATIONBAR:
return check_can_support || !fullscreen;
@ -3250,7 +3318,7 @@ bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
case TYPE_APP:
if (app_controller_)
return AppBrowserSupportsWindowFeature(feature, check_can_support);
// TODO(crbug.com/992834): Change legacy apps to TYPE_APP_POPUP.
// TODO(crbug.com/40639933): Change legacy apps to TYPE_APP_POPUP.
return AppPopupBrowserSupportsWindowFeature(feature, check_can_support);
case TYPE_DEVTOOLS:
case TYPE_APP_POPUP:
@ -3426,9 +3494,3 @@ BackgroundContents* Browser::CreateBackgroundContents(
return contents;
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
void Browser::SetURLElisionExtensionIDForTesting(const char* extension_id) {
url_elision_extension_id_ = extension_id;
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)

View file

@ -27,6 +27,7 @@
#include "chrome/browser/ui/bookmarks/bookmark_bar.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper_observer.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/browser/ui/signin/signin_view_controller.h"
@ -43,6 +44,7 @@
#include "content/public/browser/web_contents_delegate.h"
#include "extensions/buildflags/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/mojom/page/draggable_region.mojom-forward.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/ui_base_types.h"
#include "ui/base/window_open_disposition.h"
@ -61,6 +63,7 @@ class BrowserSyncedWindowDelegate;
class BrowserLocationBarModelDelegate;
class BrowserLiveTabContext;
class BrowserWindow;
class BrowserWindowFeatures;
class ExclusiveAccessManager;
class FindBarController;
class LocationBarModel;
@ -73,6 +76,10 @@ class TabStripModel;
class TabStripModelDelegate;
class TabMenuModelDelegate;
namespace tab_groups {
class DeletionDialogController;
}
namespace blink {
enum class ProtocolHandlerSecurityLevel;
}
@ -116,6 +123,10 @@ enum class BrowserClosingStatus {
kDeniedUnloadHandlersNeedTime
};
// An instance of this class represents a single browser window on Desktop. All
// features that are scoped to a browser window should have lifetime semantics
// scoped to an instance of this class, usually via direct or indirect ownership
// of a std::unique_ptr. See BrowserWindowFeatures and TabFeatures.
class Browser : public TabStripModelObserver,
public WebContentsCollection::Observer,
public content::WebContentsDelegate,
@ -126,11 +137,15 @@ class Browser : public TabStripModelObserver,
public content::PageNavigator,
public ThemeServiceObserver,
public translate::ContentTranslateDriver::TranslationObserver,
public ui::SelectFileDialog::Listener {
public ui::SelectFileDialog::Listener,
public BrowserWindowInterface {
public:
// SessionService::WindowType mirrors these values. If you add to this
// enum, look at SessionService::WindowType to see if it needs to be
// updated.
// TODO(https://crbug.com/331031753): Several of these existing Window Types
// likely should not have been using Browser as a base to begin with and
// should be migrated. Please refrain from adding new types.
enum Type {
// Normal tabbed non-app browser (previously TYPE_TABBED).
TYPE_NORMAL,
@ -174,10 +189,10 @@ class Browser : public TabStripModelObserver,
FEATURE_TOOLBAR = 1 << 2,
FEATURE_LOCATIONBAR = 1 << 3,
FEATURE_BOOKMARKBAR = 1 << 4,
// TODO(crbug.com/992834): Add FEATURE_PAGECONTROLS to describe the presence
// of per-page controls such as Content Settings Icons, which should be
// decoupled from FEATURE_LOCATIONBAR as they have independent presence in
// Web App browsers.
// TODO(crbug.com/40639933): Add FEATURE_PAGECONTROLS to describe the
// presence of per-page controls such as Content Settings Icons, which
// should be decoupled from FEATURE_LOCATIONBAR as they have independent
// presence in Web App browsers.
};
// The context for a download blocked notification from
@ -258,6 +273,11 @@ class Browser : public TabStripModelObserver,
Profile* profile,
bool user_gesture);
static CreateParams CreateForPictureInPicture(const std::string& app_name,
bool trusted_source,
Profile* profile,
bool user_gesture);
static CreateParams CreateForDevTools(Profile* profile);
// The browser type.
@ -459,6 +479,16 @@ class Browser : public TabStripModelObserver,
#endif
// Never nullptr.
//
// When the last tab is removed, the browser attempts to close, see
// TabStripEmpty().
// TODO(https://crbug.com/331031753): Several existing Browser::Types never
// show a tab strip, yet are forced to work with the tab strip API to deal
// with the previous condition. This creates confusing control flow both for
// the tab strip and this class. One or both of the following should happen:
// (1) tab_strip_model_ should become an optional member.
// (2) Variations of Browser::Type that never show a tab strip should not use
// this class.
TabStripModel* tab_strip_model() const { return tab_strip_model_.get(); }
// Never nullptr.
@ -474,6 +504,12 @@ class Browser : public TabStripModelObserver,
chrome::BrowserCommandController* command_controller() {
return command_controller_.get();
}
tab_groups::DeletionDialogController* tab_group_deletion_dialog_controller()
const {
return tab_group_deletion_dialog_controller_.get();
}
SessionID session_id() const { return session_id_; }
bool omit_from_session_restore() const { return omit_from_session_restore_; }
bool should_trigger_session_restore() const {
@ -499,6 +535,9 @@ class Browser : public TabStripModelObserver,
SigninViewController* signin_view_controller() {
return &signin_view_controller_;
}
BrowserWindowFeatures* browser_window_features() const {
return features_.get();
}
base::WeakPtr<Browser> AsWeakPtr();
base::WeakPtr<const Browser> AsWeakPtr() const;
@ -621,7 +660,7 @@ class Browser : public TabStripModelObserver,
//
// Note that there are other cases that may delay closing, such as downloads,
// but that is done before any of these steps.
// TODO(https://crbug.com/1434387): See about unifying IsBrowserClosing() and
// TODO(crbug.com/40064092): See about unifying IsBrowserClosing() and
// is_delete_scheduled().
bool IsAttemptingToCloseBrowser() const;
bool IsBrowserClosing() const;
@ -681,10 +720,6 @@ class Browser : public TabStripModelObserver,
// Saving can be disabled e.g. for the DevTools window.
bool CanSaveContents(content::WebContents* web_contents) const;
std::unique_ptr<content::WebContents> SwapWebContents(
content::WebContents* old_contents,
std::unique_ptr<content::WebContents> new_contents);
// Returns whether favicon should be shown.
bool ShouldDisplayFavicon(content::WebContents* web_contents) const;
@ -706,7 +741,10 @@ class Browser : public TabStripModelObserver,
// Interface implementations ////////////////////////////////////////////////
// Overridden from content::PageNavigator:
content::WebContents* OpenURL(const content::OpenURLParams& params) override;
content::WebContents* OpenURL(
const content::OpenURLParams& params,
base::OnceCallback<void(content::NavigationHandle&)>
navigation_handle_callback) override;
// Overridden from TabStripModelObserver:
void OnTabStripModelChanged(
@ -778,6 +816,9 @@ class Browser : public TabStripModelObserver,
void InitiatePreview(content::WebContents& web_contents,
const GURL& url) override;
bool ShouldUseInstancedSystemMediaControls() const override;
void DraggableRegionsChanged(
const std::vector<blink::mojom::DraggableRegionPtr>& regions,
content::WebContents* contents) override;
bool is_type_normal() const { return type_ == TYPE_NORMAL; }
bool is_type_popup() const { return type_ == TYPE_POPUP; }
@ -809,11 +850,6 @@ class Browser : public TabStripModelObserver,
bool ShouldRunUnloadListenerBeforeClosing(content::WebContents* web_contents);
bool RunUnloadListenerBeforeClosing(content::WebContents* web_contents);
// Set if the browser is currently participating in a tab dragging process.
// This information is used to decide if fast resize will be used during
// dragging.
void SetIsInTabDragging(bool is_in_tab_dragging);
// Sets the browser's user title. Setting it to an empty string clears it.
void SetWindowUserTitle(const std::string& user_title);
@ -828,6 +864,11 @@ class Browser : public TabStripModelObserver,
void SetForceShowBookmarkBarFlag(ForceShowBookmarkBarFlag flag);
void ClearForceShowBookmarkBarFlag(ForceShowBookmarkBarFlag flag);
// BrowserWindowInterface overrides:
views::WebView* GetWebView() override;
void OpenURL(const GURL& gurl, WindowOpenDisposition disposition) override;
const SessionID& GetSessionID() override;
private:
friend class BrowserTest;
friend class ExclusiveAccessTest;
@ -845,9 +886,6 @@ class Browser : public TabStripModelObserver,
FRIEND_TEST_ALL_PREFIXES(ExclusiveAccessTest,
TabEntersPresentationModeFromWindowed);
FRIEND_TEST_ALL_PREFIXES(BrowserCloseTest, LastGuest);
#if BUILDFLAG(ENABLE_EXTENSIONS)
FRIEND_TEST_ALL_PREFIXES(BrowserTest, URLElisionExtensionSetsPref);
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
// Used to describe why a tab is being detached. This is used by
// TabDetachedAtImpl.
@ -892,7 +930,9 @@ class Browser : public TabStripModelObserver,
// Overridden from content::WebContentsDelegate:
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
const content::OpenURLParams& params,
base::OnceCallback<void(content::NavigationHandle&)>
navigation_handle_callback) override;
void NavigationStateChanged(content::WebContents* source,
content::InvalidateTypes changed_flags) override;
void VisibleSecurityStateChanged(content::WebContents* source) override;
@ -910,8 +950,7 @@ class Browser : public TabStripModelObserver,
const gfx::Rect& bounds) override;
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
void ContentsMouseEvent(content::WebContents* source,
bool motion,
bool exited) override;
const ui::Event& event) override;
void ContentsZoomChange(bool zoom_in) override;
bool TakeFocus(content::WebContents* source, bool reverse) override;
void BeforeUnloadFired(content::WebContents* source,
@ -973,8 +1012,7 @@ class Browser : public TabStripModelObserver,
void RestoreFromWebAPI() override;
ui::WindowShowState GetWindowShowState() const override;
bool CanEnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) override;
content::RenderFrameHost* requesting_frame) override;
void EnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) override;
@ -1143,6 +1181,11 @@ class Browser : public TabStripModelObserver,
// MessageBox for when the window is closing if more than one tab is open
void MultitabResponse(chrome::MessageBoxResult result);
// Called when the user has decided whether to proceed or not with the browser
// closure, in case the cookie migration notice was shown. |proceed_closing|
// is true if the browser can be closed.
void CookieMigrationNoticeResponse(bool proceed_closing);
// Called when all warnings have completed when attempting to close the
// browser directly (e.g. via hotkey, close button, terminate signal, etc.)
// Used as a WarnBeforeClosingCallback by HandleBeforeClose().
@ -1238,8 +1281,6 @@ class Browser : public TabStripModelObserver,
const content::StoragePartitionConfig& partition_config,
content::SessionStorageNamespace* session_storage_namespace);
void SetURLElisionExtensionIDForTesting(const char* extension_id);
// Data members /////////////////////////////////////////////////////////////
PrefChangeRegistrar profile_pref_registrar_;
@ -1312,6 +1353,8 @@ class Browser : public TabStripModelObserver,
// when the browser is closed with in-progress downloads.
CancelDownloadConfirmationState cancel_download_confirmation_state_;
// State used to figure out whether we should prompt the user for confirmation
// when the browser is closed with multiple tabs open.
CancelDownloadConfirmationState close_multitab_confirmation_state_;
/////////////////////////////////////////////////////////////////////////////
@ -1370,6 +1413,10 @@ class Browser : public TabStripModelObserver,
std::unique_ptr<chrome::BrowserCommandController> command_controller_;
// Dialog controller that handles the showing of the deletion dialog.
std::unique_ptr<tab_groups::DeletionDialogController>
tab_group_deletion_dialog_controller_;
// True if the browser window has been shown at least once.
bool window_has_shown_;
@ -1415,13 +1462,7 @@ class Browser : public TabStripModelObserver,
int force_show_bookmark_bar_flags_ = ForceShowBookmarkBarFlag::kNone;
#if BUILDFLAG(ENABLE_EXTENSIONS)
// ID of an extension that historically was used to prevent URL elision in the
// omnibox, and now is being deprecated by migration to a pref. Only set by
// tests.
// TODO(crbug/324934130): remove after ~M125 or so.
static const char* url_elision_extension_id_;
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
std::unique_ptr<BrowserWindowFeatures> features_;
// The following factory is used for chrome update coalescing.
base::WeakPtrFactory<Browser> chrome_updater_factory_{this};

View file

@ -20,7 +20,6 @@
#include "components/google/core/common/google_util.h"
#include "components/offline_pages/buildflags/buildflags.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/omnibox_prefs.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/pref_registry/pref_registry_syncable.h"
@ -180,15 +179,11 @@ const gfx::VectorIcon* ChromeLocationBarModelDelegate::GetVectorIconOverride()
GetURL(&url);
if (url.SchemeIs(content::kChromeUIScheme)) {
return (OmniboxFieldTrial::IsChromeRefreshIconsEnabled())
? &omnibox::kProductChromeRefreshIcon
: &omnibox::kProductIcon;
return &omnibox::kProductChromeRefreshIcon;
}
if (url.SchemeIs(extensions::kExtensionScheme)) {
return (OmniboxFieldTrial::IsChromeRefreshIconsEnabled())
? &vector_icons::kExtensionChromeRefreshIcon
: &omnibox::kExtensionAppIcon;
return &vector_icons::kExtensionChromeRefreshIcon;
}
#endif

View file

@ -159,7 +159,7 @@ const AcceleratorMapping kAcceleratorMap[] = {
IDC_SHOW_AVATAR_MENU},
// Platform-specific key maps.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
{ui::VKEY_BROWSER_BACK, ui::EF_NONE, IDC_BACK},
{ui::VKEY_BROWSER_FORWARD, ui::EF_NONE, IDC_FORWARD},
{ui::VKEY_BROWSER_HOME, ui::EF_NONE, IDC_HOME},
@ -168,8 +168,7 @@ const AcceleratorMapping kAcceleratorMap[] = {
{ui::VKEY_BROWSER_REFRESH, ui::EF_SHIFT_DOWN, IDC_RELOAD_BYPASSING_CACHE},
{ui::VKEY_CLOSE, ui::EF_NONE, IDC_CLOSE_TAB},
{ui::VKEY_NEW, ui::EF_NONE, IDC_NEW_TAB},
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
// BUILDFLAG(IS_FUCHSIA)
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#if BUILDFLAG(IS_CHROMEOS)
// Chrome OS supports the print key, however XKB conflates the print

View file

@ -68,6 +68,7 @@
#include "chrome/browser/ui/views/page_action/page_action_icon_container.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_controller.h"
#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/send_tab_to_self/send_tab_to_self_toolbar_icon_view.h"
#include "chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
@ -231,6 +232,8 @@ ToolbarView::ToolbarView(Browser* browser, BrowserView* browser_view)
container_view_ = AddChildView(std::make_unique<ContainerView>());
SetAccessibleRole(ax::mojom::Role::kToolbar);
if (display_mode_ == DisplayMode::NORMAL) {
container_view_->SetBackground(
std::make_unique<TopContainerBackground>(browser_view));
@ -438,6 +441,12 @@ void ToolbarView::Init() {
std::make_unique<BatterySaverButton>(browser_view_));
}
if (base::FeatureList::IsEnabled(
performance_manager::features::kPerformanceIntervention)) {
performance_intervention_button_ = container_view_->AddChildView(
std::make_unique<PerformanceInterventionButton>());
}
if (cast)
cast_ = container_view_->AddChildView(std::move(cast));
@ -480,13 +489,14 @@ void ToolbarView::Init() {
const std::string sab_value = base::CommandLine::ForCurrentProcess()->
GetSwitchValueASCII("show-avatar-button");
if (sab_value == "always")
if (sab_value == "always") {
show_avatar_toolbar_button = true;
else if (sab_value == "incognito-and-guest")
} else if (sab_value == "incognito-and-guest") {
show_avatar_toolbar_button = browser_->profile()->IsIncognitoProfile() ||
browser_->profile()->IsGuestSession();
else if (sab_value == "never")
} else if (sab_value == "never") {
show_avatar_toolbar_button = false;
}
avatar_->SetVisible(show_avatar_toolbar_button);
@ -532,6 +542,13 @@ void ToolbarView::Init() {
location_bar_->Init();
show_forward_button_.Init(
prefs::kShowForwardButton, prefs,
base::BindRepeating(&ToolbarView::OnShowForwardButtonChanged,
base::Unretained(this)));
forward_->SetVisible(show_forward_button_.GetValue());
show_home_button_.Init(
prefs::kShowHomeButton, prefs,
base::BindRepeating(&ToolbarView::OnShowHomeButtonChanged,
@ -738,7 +755,8 @@ bool ToolbarView::GetAcceleratorForCommandId(
////////////////////////////////////////////////////////////////////////////////
// ToolbarView, views::View overrides:
gfx::Size ToolbarView::CalculatePreferredSize() const {
gfx::Size ToolbarView::CalculatePreferredSize(
const views::SizeBounds& available_size) const {
gfx::Size size;
switch (display_mode_) {
case DisplayMode::CUSTOM_TAB:
@ -753,7 +771,7 @@ gfx::Size ToolbarView::CalculatePreferredSize() const {
// the toolbar to report an unreasonable height (see crbug.com/985909), we
// cap the height at the size of known child views (location bar and back
// button) plus margins.
// TODO(crbug.com/1033627): Figure out why the height reports incorrectly
// TODO(crbug.com/40663413): Figure out why the height reports incorrectly
// on some installations.
if (layout_manager_ && location_bar_->GetVisible()) {
const int max_height =
@ -782,7 +800,7 @@ gfx::Size ToolbarView::GetMinimumSize() const {
// the toolbar to report an unreasonable height (see crbug.com/985909), we
// cap the height at the size of known child views (location bar and back
// button) plus margins.
// TODO(crbug.com/1033627): Figure out why the height reports incorrectly
// TODO(crbug.com/40663413): Figure out why the height reports incorrectly
// on some installations.
if (layout_manager_ && location_bar_->GetVisible()) {
const int max_height =
@ -838,7 +856,7 @@ void ToolbarView::Layout(PassKey) {
// to the overflow state determined by the first pass.
// TODO(pengchaocai): Explore possible optimizations.
if (toolbar_controller_) {
// TODO(crbug.com/1499021) Move this logic into LayoutManager.
// TODO(crbug.com/40939901) Move this logic into LayoutManager.
views::ManualLayoutUtil manual_layout_util(layout_manager_);
const bool was_overflow_button_visible =
toolbar_controller_->overflow_button()->GetVisible();
@ -1024,7 +1042,7 @@ void ToolbarView::InitLayout() {
if (base::FeatureList::IsEnabled(features::kResponsiveToolbar)) {
constexpr int kToolbarFlexOrderStart = 1;
// TODO(crbug.com/1479588): Ignore containers till issue addressed.
// TODO(crbug.com/40929989): Ignore containers till issue addressed.
toolbar_controller_ = std::make_unique<ToolbarController>(
ToolbarController::GetDefaultResponsiveElements(browser_),
ToolbarController::GetDefaultOverflowOrder(), kToolbarFlexOrderStart,
@ -1111,6 +1129,16 @@ void ToolbarView::UpdateTypeAndSeverity(
}
app_menu_button_->SetAccessibleName(accname_app);
app_menu_button_->SetTypeAndSeverity(type_and_severity);
if (base::FeatureList::IsEnabled(features::kDefaultBrowserPromptRefresh) &&
DefaultBrowserPromptManager::GetInstance()->get_show_app_menu_prompt()) {
// Anytime the default chip is eligible to be shown, log whether the prompt
// was actually shown. This helps us understand how often it is pre-empted.
base::UmaHistogramBoolean(
"DefaultBrowser.AppMenu.DefaultChipShown",
type_and_severity.type ==
AppMenuIconController::IconType::DEFAULT_BROWSER_PROMPT);
}
}
SkColor ToolbarView::GetDefaultColorForSeverity(
@ -1180,7 +1208,8 @@ views::AccessiblePaneView* ToolbarView::GetAsAccessiblePaneView() {
return this;
}
views::View* ToolbarView::GetAnchorView(PageActionIconType type) {
views::View* ToolbarView::GetAnchorView(
std::optional<PageActionIconType> type) {
return location_bar_;
}
@ -1249,10 +1278,13 @@ void ToolbarView::LoadImages() {
extensions_container_->UpdateAllIcons();
}
void ToolbarView::OnShowForwardButtonChanged() {
forward_->SetVisible(show_forward_button_.GetValue());
InvalidateLayout();
}
void ToolbarView::OnShowHomeButtonChanged() {
home_->SetVisible(show_home_button_.GetValue());
DeprecatedLayoutImmediately();
SchedulePaint();
}
void ToolbarView::OnTouchUiChanged() {

View file

@ -7,6 +7,7 @@
#include <memory>
#include <utility>
#include "base/containers/heap_array.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
@ -225,12 +226,12 @@ bool BaseFile::ValidateDataInFile(int64_t offset,
if (data_len <= 0)
return true;
std::unique_ptr<char[]> buffer(new char[data_len]);
int bytes_read = file_.Read(offset, buffer.get(), data_len);
auto buffer = base::HeapArray<char>::Uninit(data_len);
int bytes_read = file_.Read(offset, buffer.data(), buffer.size());
if (bytes_read < 0 || static_cast<size_t>(bytes_read) < data_len)
return false;
return memcmp(data, buffer.get(), data_len) == 0;
return memcmp(data, buffer.data(), buffer.size()) == 0;
}
DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {

View file

@ -24,9 +24,6 @@ bool MachineIdProvider::HasId() {
// On non-windows, the machine id is based on the hardware model name.
// This will suffice as users are unlikely to change to the same machine model.
std::string MachineIdProvider::GetMachineId() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch("disable-machine-id")) {
return std::string();
}
// Gets hardware model name. (e.g. 'Macbook Pro 16,1', 'iPhone 9,3')
std::string hardware_model_name = base::SysInfo::HardwareModelName();

View file

@ -5,6 +5,7 @@
#include "components/metrics/machine_id_provider.h"
#include <windows.h>
#include <stdint.h>
#include <winioctl.h>

View file

@ -126,4 +126,8 @@ bool DPAPIKeyProvider::UseForEncryption() {
return true;
}
bool DPAPIKeyProvider::IsCompatibleWithOsCryptSync() {
return true;
}
} // namespace os_crypt_async

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/os_crypt/sync/os_crypt.h"
#include <windows.h>
#include "base/base64.h"
@ -16,7 +18,6 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/wincrypt_shim.h"
#include "components/os_crypt/sync/os_crypt.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"

View file

@ -63,7 +63,6 @@ source_set("browser") {
"//base",
"//base:base_static",
"//base:clang_profiling_buildflags",
"//base/third_party/dynamic_annotations",
"//base/tracing/protos:chrome_track_event_resources",
"//build:branding_buildflags",
"//build:chromecast_buildflags",
@ -111,6 +110,7 @@ source_set("browser") {
"//components/url_formatter",
"//components/variations",
"//components/variations/net",
"//components/version_info",
"//components/viz/client",
"//components/viz/common",
"//components/viz/host",
@ -222,10 +222,12 @@ source_set("browser") {
"//services/video_capture:lib",
"//services/video_capture/public/cpp",
"//services/video_capture/public/mojom:constants",
"//services/video_effects/public/mojom:mojom",
"//services/viz/privileged/mojom",
"//services/viz/public/cpp/gpu",
"//services/viz/public/mojom",
"//services/webnn/public/mojom",
"//services/webnn:webnn_service",
"//services/webnn:webnn_switches",
"//skia",
"//skia/public/mojom",
"//storage/browser",
@ -277,6 +279,7 @@ source_set("browser") {
"//ui/events/devices",
"//ui/events/gestures/blink",
"//ui/gfx",
"//ui/gfx:color_utils",
"//ui/gfx/animation",
"//ui/gfx/geometry",
"//ui/gfx/geometry/mojom",
@ -414,8 +417,6 @@ source_set("browser") {
"aggregation_service/report_scheduler_timer.h",
"attribution_reporting/aggregatable_attribution_utils.cc",
"attribution_reporting/aggregatable_attribution_utils.h",
"attribution_reporting/aggregatable_histogram_contribution.cc",
"attribution_reporting/aggregatable_histogram_contribution.h",
"attribution_reporting/attribution_background_registrations_id.h",
"attribution_reporting/attribution_beacon_id.h",
"attribution_reporting/attribution_config.cc",
@ -485,7 +486,6 @@ source_set("browser") {
"attribution_reporting/storable_source.h",
"attribution_reporting/store_source_result.cc",
"attribution_reporting/store_source_result.h",
"attribution_reporting/store_source_result_internal.h",
"attribution_reporting/stored_source.cc",
"attribution_reporting/stored_source.h",
"audio/audio_service.cc",
@ -761,8 +761,6 @@ source_set("browser") {
"cookie_store/cookie_store_host.h",
"cookie_store/cookie_store_manager.cc",
"cookie_store/cookie_store_manager.h",
"coop_related_group.cc",
"coop_related_group.h",
"data_url_loader_factory.cc",
"data_url_loader_factory.h",
"device/device_service.cc",
@ -889,6 +887,8 @@ source_set("browser") {
"devtools/protocol/tracing_handler.h",
"devtools/render_frame_devtools_agent_host.cc",
"devtools/render_frame_devtools_agent_host.h",
"devtools/request_body_collector.cc",
"devtools/request_body_collector.h",
"devtools/service_worker_devtools_agent_host.cc",
"devtools/service_worker_devtools_agent_host.h",
"devtools/service_worker_devtools_manager.cc",
@ -1159,6 +1159,8 @@ source_set("browser") {
"interest_group/interest_group_permissions_checker.h",
"interest_group/interest_group_priority_util.cc",
"interest_group/interest_group_priority_util.h",
"interest_group/interest_group_real_time_report_util.cc",
"interest_group/interest_group_real_time_report_util.h",
"interest_group/interest_group_storage.cc",
"interest_group/interest_group_storage.h",
"interest_group/interest_group_update.cc",
@ -1333,11 +1335,8 @@ source_set("browser") {
"memory_pressure/user_level_memory_pressure_signal_generator.cc",
"memory_pressure/user_level_memory_pressure_signal_generator.h",
"message_port_provider.cc",
"metrics/histogram_controller.cc",
"metrics/histogram_controller.h",
"metrics/histogram_shared_memory_config.cc",
"metrics/histogram_shared_memory_config.h",
"metrics/histogram_subscriber.h",
"metrics/histogram_synchronizer.cc",
"metrics/histogram_synchronizer.h",
"metrics/histograms_internals_ui.cc",
@ -1350,6 +1349,10 @@ source_set("browser") {
"ml/ml_service_factory.h",
"ml/ml_service_impl.cc",
"ml/ml_service_impl.h",
"model_execution/mock_model_execution_session.cc",
"model_execution/mock_model_execution_session.h",
"model_execution/mock_model_manager.cc",
"model_execution/mock_model_manager.h",
"mojo_binder_policy_applier.cc",
"mojo_binder_policy_applier.h",
"mojo_binder_policy_map_impl.cc",
@ -1363,8 +1366,6 @@ source_set("browser") {
"network/cookie_store_factory.cc",
"network/cross_origin_embedder_policy_reporter.cc",
"network/cross_origin_embedder_policy_reporter.h",
"network/cross_origin_opener_policy_reporter.cc",
"network/cross_origin_opener_policy_reporter.h",
"network/http_cache_backend_file_operations_factory.cc",
"network/http_cache_backend_file_operations_factory.h",
"network/network_errors_listing_ui.cc",
@ -1511,6 +1512,7 @@ source_set("browser") {
"preloading/preloading.h",
"preloading/preloading_attempt_impl.cc",
"preloading/preloading_attempt_impl.h",
"preloading/preloading_confidence.h",
"preloading/preloading_config.cc",
"preloading/preloading_config.h",
"preloading/preloading_data_impl.cc",
@ -1545,6 +1547,8 @@ source_set("browser") {
"preloading/prerender/prerender_navigation_utils.h",
"preloading/prerender/prerender_new_tab_handle.cc",
"preloading/prerender/prerender_new_tab_handle.h",
"preloading/prerender/prerender_no_vary_search_commit_deferring_condition.cc",
"preloading/prerender/prerender_no_vary_search_commit_deferring_condition.h",
"preloading/prerender/prerender_subframe_navigation_throttle.cc",
"preloading/prerender/prerender_subframe_navigation_throttle.h",
"preloading/prerenderer.h",
@ -1635,11 +1639,6 @@ source_set("browser") {
"renderer_host/concurrent_navigations_commit_deferring_condition.h",
"renderer_host/cookie_utils.cc",
"renderer_host/cookie_utils.h",
"renderer_host/coop_swap_result.h",
"renderer_host/cross_origin_opener_policy_access_report_manager.cc",
"renderer_host/cross_origin_opener_policy_access_report_manager.h",
"renderer_host/cross_origin_opener_policy_status.cc",
"renderer_host/cross_origin_opener_policy_status.h",
"renderer_host/cross_process_frame_connector.cc",
"renderer_host/cross_process_frame_connector.h",
"renderer_host/cursor_manager.cc",
@ -1822,10 +1821,6 @@ source_set("browser") {
"renderer_host/page_impl.h",
"renderer_host/page_lifecycle_state_manager.cc",
"renderer_host/page_lifecycle_state_manager.h",
"renderer_host/pending_beacon_host.cc",
"renderer_host/pending_beacon_host.h",
"renderer_host/pending_beacon_service.cc",
"renderer_host/pending_beacon_service.h",
"renderer_host/policy_container_host.cc",
"renderer_host/policy_container_host.h",
"renderer_host/private_network_access_util.cc",
@ -1879,8 +1874,6 @@ source_set("browser") {
"renderer_host/render_widget_host_view_aura.h",
"renderer_host/render_widget_host_view_base.cc",
"renderer_host/render_widget_host_view_base.h",
"renderer_host/render_widget_host_view_base_observer.cc",
"renderer_host/render_widget_host_view_base_observer.h",
"renderer_host/render_widget_host_view_child_frame.cc",
"renderer_host/render_widget_host_view_child_frame.h",
"renderer_host/render_widget_targeter.cc",
@ -1916,8 +1909,6 @@ source_set("browser") {
"resource_context_impl.cc",
"resource_context_impl.h",
"resource_coordinator_service.cc",
"runtime_feature_state/runtime_feature_state_document_data.cc",
"runtime_feature_state/runtime_feature_state_document_data.h",
"scheduler/browser_io_thread_delegate.cc",
"scheduler/browser_io_thread_delegate.h",
"scheduler/browser_task_executor.cc",
@ -1952,6 +1943,15 @@ source_set("browser") {
"screenlock_monitor/screenlock_monitor_device_source.h",
"screenlock_monitor/screenlock_monitor_source.cc",
"screenlock_monitor/screenlock_monitor_source.h",
"security/coop/coop_related_group.cc",
"security/coop/coop_related_group.h",
"security/coop/coop_swap_result.h",
"security/coop/cross_origin_opener_policy_access_report_manager.cc",
"security/coop/cross_origin_opener_policy_access_report_manager.h",
"security/coop/cross_origin_opener_policy_reporter.cc",
"security/coop/cross_origin_opener_policy_reporter.h",
"security/coop/cross_origin_opener_policy_status.cc",
"security/coop/cross_origin_opener_policy_status.h",
"service_process_host_impl.cc",
"service_worker/embedded_worker_instance.cc",
"service_worker/embedded_worker_instance.h",
@ -2096,6 +2096,8 @@ source_set("browser") {
"speech/speech_recognition_dispatcher_host.h",
"speech/speech_recognition_manager_impl.cc",
"speech/speech_recognition_manager_impl.h",
"speech/speech_recognition_session.cc",
"speech/speech_recognition_session.h",
"speech/speech_recognizer.h",
"speech/speech_synthesis_impl.cc",
"speech/speech_synthesis_impl.h",
@ -2339,11 +2341,11 @@ source_set("browser") {
]
}
# TODO(crbug.com/1327384): Remove `permissions_common`.
# TODO(crbug.com/40226169): Remove `permissions_common`.
# DO NOT add unrelated entries to this block.
deps += [ "//components/permissions:permissions_common" ]
# TODO(crbug.com/1327384): Remove `permission_util.*`.
# TODO(crbug.com/40226169): Remove `permission_util.*`.
# DO NOT add unrelated entries to this block.
sources += [
"permissions/permission_util.cc",
@ -2637,6 +2639,10 @@ source_set("browser") {
]
} else if (is_ios) {
sources += [
"accessibility/browser_accessibility_ios.h",
"accessibility/browser_accessibility_ios.mm",
"accessibility/browser_accessibility_manager_ios.h",
"accessibility/browser_accessibility_manager_ios.mm",
"child_process_launcher_helper_ios.mm",
"date_time_chooser/ios/date_time_chooser_coordinator.h",
"date_time_chooser/ios/date_time_chooser_coordinator.mm",
@ -2660,6 +2666,10 @@ source_set("browser") {
"renderer_host/popup_menu_helper_ios.mm",
"renderer_host/render_widget_host_view_ios.h",
"renderer_host/render_widget_host_view_ios.mm",
"renderer_host/render_widget_host_view_ios_uiview.h",
"renderer_host/render_widget_host_view_ios_uiview.mm",
"renderer_host/render_widget_host_view_ios_uiview_textinput.h",
"renderer_host/render_widget_host_view_ios_uiview_textinput.mm",
"renderer_host/web_menu_runner_ios.h",
"renderer_host/web_menu_runner_ios.mm",
"speech/tts_ios.mm",
@ -2817,12 +2827,8 @@ source_set("browser") {
"speech/tts_win.cc",
"utility_sandbox_delegate_win.cc",
]
defines += [
# This prevents the inclusion of atlhost.h which paired
# with the windows 8 sdk it does the wrong thing.
"__ATLHOST_H__",
]
deps += [
"//components/app_launch_prefetch",
"//content/utility:delegate_data",
"//services/screen_ai/public/cpp:utilities",
"//third_party/blink/public/common:font_unique_name_table_proto",
@ -3043,6 +3049,7 @@ source_set("browser") {
"android/content_url_loader_factory.cc",
"android/content_url_loader_factory.h",
"android/content_view_statics.cc",
"android/content_web_feature_usage_utils_android.cc",
"android/devtools_auth.cc",
"android/dialog_overlay_impl.cc",
"android/dialog_overlay_impl.h",
@ -3305,11 +3312,23 @@ source_set("browser") {
"picture_in_picture/document_picture_in_picture_window_controller_impl.h",
]
if (!is_fuchsia) {
sources += [
"speech/soda_speech_recognition_engine_impl.cc",
"speech/soda_speech_recognition_engine_impl.h",
]
}
deps += [
"//components/soda:constants",
"//components/soda:soda",
"//components/soda:utils",
"//components/speech:speech",
"//components/vector_icons",
"//components/webauthn/json",
"//content/browser/tracing:resources",
"//media/mojo/mojom:speech_recognition",
"//ui/base",
]
}

View file

@ -203,7 +203,7 @@ bool FileSystemAccessSafeMoveHelper::RequireAfterWriteChecks() const {
if (!source_url().IsInSameFileSystem(dest_url()))
return true;
// TODO(crbug.com/1250534): Properly handle directory moves here, for
// TODO(crbug.com/40198034): Properly handle directory moves here, for
// which extension checks don't make sense.
auto source_extension = source_url().path().Extension();
auto dest_extension = dest_url().path().Extension();

View file

@ -15,7 +15,7 @@
namespace content {
// TODO(crbug.com/1250534): Support safely moving directories. For now, this
// TODO(crbug.com/40198034): Support safely moving directories. For now, this
// class only supports moving files. Moving directories will require running
// safe browsing checks on all files before moving.
//

View file

@ -0,0 +1,612 @@
// Copyright 2024 The Chromium Authors and Alex313031
// TODO: Alex313031 - DELETE AFTER M127!!
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/filters/win/media_foundation_audio_decoder.h"
#include <mfapi.h>
#include <mferror.h>
#include <stdint.h>
#include <wmcodecdsp.h>
#include "base/auto_reset.h"
#include "base/containers/span.h"
#include "base/containers/span_writer.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/task/bind_post_task.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/windows_version.h"
#include "media/base/audio_buffer.h"
#include "media/base/audio_discard_helper.h"
#include "media/base/audio_sample_types.h"
#include "media/base/limits.h"
#include "media/base/status.h"
#include "media/base/timestamp_constants.h"
#include "media/base/win/mf_helpers.h"
#include "media/base/win/mf_initializer.h"
namespace media {
namespace {
bool CodecSupportsFloatOutput(AudioCodec codec) {
#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
if (codec == AudioCodec::kAC3 || codec == AudioCodec::kEAC3) {
return true;
}
#endif
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
if (codec == AudioCodec::kAAC) {
return true;
}
#endif
#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
if (codec == AudioCodec::kAC4) {
return true;
}
#endif
return false;
}
bool CodecSupportsFormat(const AudioDecoderConfig& config,
const WAVEFORMATEX& format) {
if (config.channels() == format.nChannels &&
config.samples_per_second() == static_cast<int>(format.nSamplesPerSec)) {
return true;
}
// Sometimes HE-AAC configurations may be off by a factor of two, so allow
// such cases -- they'll reconfigure upon first decoded frame.
if (config.codec() == AudioCodec::kAAC &&
2 * config.channels() == format.nChannels &&
2 * config.samples_per_second() ==
static_cast<int>(format.nSamplesPerSec)) {
return true;
}
// For AC3/EAC3, we expect channel config changes, no need to compare channels
// here.
if ((config.codec() == AudioCodec::kAC3 ||
config.codec() == AudioCodec::kEAC3) &&
config.samples_per_second() == static_cast<int>(format.nSamplesPerSec)) {
return true;
}
if (config.codec() == AudioCodec::kAC4) {
return true;
}
return false;
}
std::optional<MFT_REGISTER_TYPE_INFO> GetTypeInfo(
const AudioDecoderConfig& config) {
switch (config.codec()) {
#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
case AudioCodec::kDTSXP2:
return MFT_REGISTER_TYPE_INFO{MFMediaType_Audio, MFAudioFormat_DTS_UHD};
case AudioCodec::kDTS:
case AudioCodec::kDTSE:
return MFT_REGISTER_TYPE_INFO{MFMediaType_Audio, MFAudioFormat_DTS_RAW};
#endif
#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
case AudioCodec::kAC3:
return MFT_REGISTER_TYPE_INFO{MFMediaType_Audio, MFAudioFormat_Dolby_AC3};
case AudioCodec::kEAC3:
return MFT_REGISTER_TYPE_INFO{MFMediaType_Audio,
MFAudioFormat_Dolby_DDPlus};
#endif
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
case AudioCodec::kAAC:
if (config.profile() == AudioCodecProfile::kXHE_AAC &&
base::win::GetVersion() >= base::win::Version::WIN11_22H2) {
return MFT_REGISTER_TYPE_INFO{MFMediaType_Audio, MFAudioFormat_AAC};
}
[[fallthrough]];
#endif
#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
case AudioCodec::kAC4:
return MFT_REGISTER_TYPE_INFO{MFMediaType_Audio, MFAudioFormat_Dolby_AC4};
#endif // BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
default:
return std::nullopt;
}
}
bool PopulateInputSample(IMFSample* sample, const DecoderBuffer& input) {
Microsoft::WRL::ComPtr<IMFMediaBuffer> buffer;
HRESULT hr = sample->GetBufferByIndex(0, &buffer);
RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from sample", false);
DWORD max_length = 0;
DWORD current_length = 0;
uint8_t* destination_ptr = nullptr;
hr = buffer->Lock(&destination_ptr, &max_length, &current_length);
RETURN_ON_HR_FAILURE(hr, "Failed to lock buffer", false);
// SAFETY: IMFMediaBuffer::Lock returns a pointer that points to at least
// `max_length` many bytes.
// https://learn.microsoft.com/en-us/windows/win32/api/mfobjects/nf-mfobjects-imfmediabuffer-lock
auto destination = UNSAFE_BUFFERS(base::span(destination_ptr, max_length));
RETURN_ON_FAILURE(!current_length, "Input length is zero", false);
RETURN_ON_FAILURE(input.size() <= max_length, "Input length is too long",
false);
destination.first(input.size()).copy_from(input);
hr = buffer->SetCurrentLength(input.size());
RETURN_ON_HR_FAILURE(hr, "Failed to set buffer length", false);
hr = buffer->Unlock();
RETURN_ON_HR_FAILURE(hr, "Failed to unlock buffer", false);
RETURN_ON_HR_FAILURE(
sample->SetSampleTime(input.timestamp().InNanoseconds() / 100),
"Failed to set input timestamp", false);
RETURN_ON_HR_FAILURE(
sample->SetSampleDuration(input.duration().InNanoseconds() / 100),
"Failed to set input duration", false);
return true;
}
int GetBytesPerFrame(AudioCodec codec) {
switch (codec) {
#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
// DTS Sound Unbound MFT v1.3 supports 24-bit PCM output only
case AudioCodec::kDTS:
case AudioCodec::kDTSE:
case AudioCodec::kDTSXP2:
return 3;
#endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
default:
return 4;
}
}
} // namespace
// static
std::unique_ptr<MediaFoundationAudioDecoder>
MediaFoundationAudioDecoder::Create() {
return InitializeMediaFoundation()
? std::make_unique<MediaFoundationAudioDecoder>()
: nullptr;
}
MediaFoundationAudioDecoder::MediaFoundationAudioDecoder() = default;
MediaFoundationAudioDecoder::~MediaFoundationAudioDecoder() = default;
AudioDecoderType MediaFoundationAudioDecoder::GetDecoderType() const {
return AudioDecoderType::kMediaFoundation;
}
void MediaFoundationAudioDecoder::Initialize(const AudioDecoderConfig& config,
CdmContext* cdm_context,
InitCB init_cb,
const OutputCB& output_cb,
const WaitingCB& waiting_cb) {
if (config.is_encrypted()) {
std::move(init_cb).Run(
DecoderStatus(DecoderStatus::Codes::kUnsupportedEncryptionMode,
"MFT Codec does not support encrypted content"));
return;
}
config_ = config;
output_cb_ = output_cb;
base::BindPostTaskToCurrentDefault(std::move(init_cb))
.Run(CreateDecoder()
? DecoderStatus(OkStatus())
: DecoderStatus(DecoderStatus::Codes::kUnsupportedCodec));
}
void MediaFoundationAudioDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) {
DecodeCB decode_cb_bound =
base::BindPostTaskToCurrentDefault(std::move(decode_cb));
if (buffer->end_of_stream()) {
switch (decoder_->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0)) {
case S_OK: {
OutputStatus rc;
do {
rc = PumpOutput(PumpState::kNormal);
} while (rc == OutputStatus::kSuccess);
// Return kOk if more input is needed since this is end of stream
std::move(decode_cb_bound)
.Run(rc == OutputStatus::kFailed ? DecoderStatus::Codes::kFailed
: DecoderStatus::Codes::kOk);
return;
}
case MF_E_TRANSFORM_TYPE_NOT_SET:
std::move(decode_cb_bound)
.Run(DecoderStatus::Codes::kPlatformDecodeFailure);
return;
default:
std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
return;
}
}
if (buffer->is_encrypted()) {
DLOG(ERROR) << "Encrypted buffer not supported";
std::move(decode_cb_bound)
.Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
return;
}
if (buffer->timestamp() == kNoTimestamp) {
DLOG(ERROR) << "Received a buffer without timestamps!";
std::move(decode_cb_bound).Run(DecoderStatus::Codes::kMissingTimestamp);
return;
}
if (has_reset_) {
ResetTimestampState();
has_reset_ = false;
}
auto sample = CreateEmptySampleWithBuffer(buffer->size(), 0);
if (!sample) {
std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
return;
}
if (!PopulateInputSample(sample.Get(), *buffer)) {
std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
return;
}
auto hr = decoder_->ProcessInput(0, sample.Get(), 0);
if (hr != S_OK && hr != MF_E_NOTACCEPTING) {
DecoderStatus::Codes rc;
switch (hr) {
case MF_E_NO_SAMPLE_DURATION:
rc = DecoderStatus::Codes::kDecoderStreamInErrorState;
break;
case MF_E_TRANSFORM_TYPE_NOT_SET:
rc = DecoderStatus::Codes::kPlatformDecodeFailure;
break;
case MF_E_NO_SAMPLE_TIMESTAMP:
rc = DecoderStatus::Codes::kMissingTimestamp;
break;
default:
rc = DecoderStatus::Codes::kFailed;
break;
}
// Drop remaining samples on error, no need to call PumpOutput
std::move(decode_cb_bound).Run(rc);
return;
}
current_buffer_time_info_ = buffer->time_info();
bool decoded_frame_this_loop = false;
OutputStatus rc;
do {
rc = PumpOutput(PumpState::kNormal);
if (rc == OutputStatus::kNeedMoreInput)
break;
if (rc == OutputStatus::kFailed) {
std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
return;
}
decoded_frame_this_loop = true;
} while (rc == OutputStatus::kSuccess);
// Even if we didn't decode a frame this loop, we should still send the packet
// to the discard helper for caching.
if (!decoded_frame_this_loop && !buffer->end_of_stream()) {
const bool result =
discard_helper_->ProcessBuffers(current_buffer_time_info_, nullptr);
DCHECK(!result);
}
std::move(decode_cb_bound).Run(OkStatus());
}
void MediaFoundationAudioDecoder::Reset(base::OnceClosure reset_cb) {
has_reset_ = true;
auto hr = decoder_->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
if (hr != S_OK) {
DLOG(ERROR) << "Reset failed with \"" << PrintHr(hr) << "\"";
}
base::BindPostTaskToCurrentDefault(std::move(reset_cb)).Run();
}
bool MediaFoundationAudioDecoder::NeedsBitstreamConversion() const {
// DTS does not require any header/bit stream conversion
return false;
}
bool MediaFoundationAudioDecoder::CreateDecoder() {
auto type_info = GetTypeInfo(config_);
// This shouldn't be possible outside of tests since production code will use
// the MediaFoundationAudioDecoder::Create() which enforces this.
if (!type_info || !InitializeMediaFoundation()) {
return false;
}
// Find the decoder factory.
//
// Note: It'd be nice if there was an asynchronous MFT (to avoid the need
// for a codec pump), but alas MFT_ENUM_FLAG_ASYNC_MFT returns no matches :(
base::win::ScopedCoMem<IMFActivate*> acts;
UINT32 acts_num = 0;
MFTEnumEx(MFT_CATEGORY_AUDIO_DECODER,
MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT |
MFT_ENUM_FLAG_SORTANDFILTER,
&type_info.value(), nullptr, &acts, &acts_num);
if (acts_num < 1) {
return false;
}
// Create the decoder from the factory. Activate the first MFT object.
RETURN_ON_HR_FAILURE(acts[0]->ActivateObject(IID_PPV_ARGS(&decoder_)),
"Failed to activate MFT", false);
// Release all activated and unactivated object after creating the decoder
for (UINT32 curr_act = 0; curr_act < acts_num; ++curr_act) {
acts[curr_act]->Release();
}
Microsoft::WRL::ComPtr<IMFMediaType> input_type;
auto hr = E_NOTIMPL;
if (config_.codec() == AudioCodec::kAAC) {
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
hr = GetAacAudioType(config_, &input_type);
#endif
} else {
hr = GetDefaultAudioType(config_, &input_type);
}
RETURN_ON_HR_FAILURE(hr, "Failed to create IMFMediaType for input data",
false);
RETURN_ON_HR_FAILURE(decoder_->SetInputType(0, input_type.Get(), 0),
"Failed to set input type for IMFTransform", false);
return ConfigureOutput();
}
bool MediaFoundationAudioDecoder::ConfigureOutput() {
// Reset sample staging buffer before configure output, in case stream
// configuration changed.
output_sample_.Reset();
Microsoft::WRL::ComPtr<IMFMediaType> output_type;
for (uint32_t i = 0;
SUCCEEDED(decoder_->GetOutputAvailableType(0, i, &output_type)); ++i) {
GUID out_type;
RETURN_ON_HR_FAILURE(output_type->GetGUID(MF_MT_MAJOR_TYPE, &out_type),
"Failed to get output main type", false);
GUID out_subtype;
RETURN_ON_HR_FAILURE(output_type->GetGUID(MF_MT_SUBTYPE, &out_subtype),
"Failed to get output subtype", false);
#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
// Configuration specific to DTS Sound Unbound MFT v1.3.0
// DTS-CA 5.1 (6 channels)
constexpr uint32_t DTS_5_1 = 2;
// DTS:X P2 5.1 (6 channels) or 5.1.4 (downmix to 6 channels)
constexpr uint32_t DTSX_5_1_DOWNMIX = 3;
if ((out_subtype == MFAudioFormat_PCM) &&
((config_.codec() == AudioCodec::kDTS && i == DTS_5_1) ||
(config_.codec() == AudioCodec::kDTSE && i == DTS_5_1) ||
(config_.codec() == AudioCodec::kDTSXP2 && i == DTSX_5_1_DOWNMIX))) {
RETURN_ON_HR_FAILURE(decoder_->SetOutputType(0, output_type.Get(), 0),
"Failed to set output type IMFTransform", false);
RETURN_ON_HR_FAILURE(
output_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &channel_count_),
"Failed to get output channel count", false);
MFT_OUTPUT_STREAM_INFO info = {0};
RETURN_ON_HR_FAILURE(decoder_->GetOutputStreamInfo(0, &info),
"Failed to get output stream info", false);
if (channel_count_ == 6) {
output_sample_ =
CreateEmptySampleWithBuffer(info.cbSize, info.cbAlignment);
RETURN_ON_FAILURE(!!output_sample_, "Failed to create staging sample",
false);
}
}
#endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
if (CodecSupportsFloatOutput(config_.codec()) &&
out_subtype == MFAudioFormat_Float) {
base::win::ScopedCoMem<WAVEFORMATEX> wave_format;
UINT32 wave_format_size;
RETURN_ON_HR_FAILURE(
MFCreateWaveFormatExFromMFMediaType(output_type.Get(), &wave_format,
&wave_format_size),
"Failed to get waveformat for media type", false);
if (CodecSupportsFormat(config_, *wave_format)) {
RETURN_ON_HR_FAILURE(decoder_->SetOutputType(0, output_type.Get(), 0),
"Failed to set output type IMFTransform", false);
MFT_OUTPUT_STREAM_INFO info = {0};
RETURN_ON_HR_FAILURE(decoder_->GetOutputStreamInfo(0, &info),
"Failed to get output stream info", false);
output_sample_ =
CreateEmptySampleWithBuffer(info.cbSize, info.cbAlignment);
RETURN_ON_FAILURE(!!output_sample_, "Failed to create staging sample",
false);
channel_count_ = wave_format->nChannels;
}
}
if (!output_sample_) {
output_type.Reset();
continue;
}
// Check the optional channel mask argument.
ChannelConfig mask = 0u;
auto hr = output_type->GetUINT32(MF_MT_AUDIO_CHANNEL_MASK, &mask);
if (hr == MF_E_ATTRIBUTENOTFOUND) {
channel_layout_ = GuessChannelLayout(channel_count_);
} else {
RETURN_ON_HR_FAILURE(hr, "Failed to get output channel mask", false);
channel_layout_ = ChannelConfigToChannelLayout(mask);
RETURN_ON_FAILURE(static_cast<uint32_t>(ChannelLayoutToChannelCount(
channel_layout_)) == channel_count_ ||
channel_layout_ == CHANNEL_LAYOUT_DISCRETE,
"Channel layout and channel count don't match", false);
}
const auto current_sample_rate = sample_rate_;
RETURN_ON_HR_FAILURE(
output_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &sample_rate_),
"Failed to get output sample rate", false);
RETURN_ON_FAILURE(
channel_count_ > 0 && channel_count_ <= limits::kMaxChannels,
"Channel count is not supported", false);
RETURN_ON_FAILURE(sample_rate_ >= limits::kMinSampleRate &&
sample_rate_ <= limits::kMaxSampleRate,
"Sample rate is not supported", false);
if (current_sample_rate != sample_rate_) {
ResetTimestampState();
}
decoder_->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
return true;
}
return false;
}
MediaFoundationAudioDecoder::OutputStatus
MediaFoundationAudioDecoder::PumpOutput(PumpState pump_state) {
// Unlike video, the audio MFT requires that we provide the output sample
// instead of allocating it for us.
MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0};
output_data_buffer.pSample = output_sample_.Get();
DWORD status = 0;
auto hr = decoder_->ProcessOutput(0, 1, &output_data_buffer, &status);
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
DVLOG(3) << __func__ << "More input needed to decode outputs.";
return OutputStatus::kNeedMoreInput;
}
if (hr == MF_E_TRANSFORM_STREAM_CHANGE &&
pump_state != PumpState::kStreamChange) {
if (!ConfigureOutput()) {
return OutputStatus::kFailed;
}
DVLOG(1) << "New config: ch=" << channel_count_ << ", sr=" << sample_rate_
<< " (" << config_.AsHumanReadableString() << ")";
PumpOutput(PumpState::kStreamChange);
return OutputStatus::kStreamChange;
}
RETURN_ON_HR_FAILURE(hr, "Failed to process output", OutputStatus::kFailed);
// Unused, but must be released.
IMFCollection* events = output_data_buffer.pEvents;
if (events)
events->Release();
Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
RETURN_ON_HR_FAILURE(
output_sample_->ConvertToContiguousBuffer(&output_buffer),
"Failed to map sample into a contiguous output buffer",
OutputStatus::kFailed);
DWORD current_length = 0;
uint8_t* destination_ptr = nullptr;
RETURN_ON_HR_FAILURE(
output_buffer->Lock(&destination_ptr, NULL, &current_length),
"Failed to lock output buffer", OutputStatus::kFailed);
// SAFETY: IMFMediaBuffer::Lock returns a pointer that points to at least
// `current_length` many bytes (and up to a larger max, which we discard).
// https://learn.microsoft.com/en-us/windows/win32/api/mfobjects/nf-mfobjects-imfmediabuffer-lock
auto destination =
UNSAFE_BUFFERS(base::span(destination_ptr, current_length));
// Output is always configured to be interleaved float.
int sample_byte_len = GetBytesPerFrame(config_.codec());
size_t frames = (current_length / sample_byte_len / channel_count_);
RETURN_ON_FAILURE(frames > 0u, "Invalid output buffer size",
OutputStatus::kFailed);
if (!pool_)
pool_ = base::MakeRefCounted<AudioBufferMemoryPool>();
scoped_refptr<AudioBuffer> audio_buffer;
#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
// DTS Sound Unbound MFT v1.3.0 outputs 24-bit PCM samples, and will
// be converted to 32-bit float
if (config_.codec() == AudioCodec::kDTS ||
config_.codec() == AudioCodec::kDTSE ||
config_.codec() == AudioCodec::kDTSXP2) {
audio_buffer =
AudioBuffer::CreateBuffer(kSampleFormatF32, channel_layout_,
channel_count_, sample_rate_, frames, pool_);
auto channel_data = base::SpanWriter<uint8_t>(
// TODO(crbug.com/40284755): channel_data() should be an array of spans,
// not unbounded pointers. This span is constructed unsoundly.
UNSAFE_BUFFERS(base::span(audio_buffer->channel_data()[0u],
frames * channel_count_ * 4u)));
for (uint64_t i = 0; i < frames; i++) {
for (uint64_t ch = 0; ch < channel_count_; ch++) {
auto a = static_cast<int8_t>(destination[0u]);
auto b = static_cast<int8_t>(destination[1u]);
auto c = static_cast<int8_t>(destination[2u]);
int32_t pcmi = (int32_t{a} << 8) & 0xff00;
pcmi |= (int32_t{b} << 16) & 0xff0000;
pcmi |= (int32_t{c} << 24) & 0xff000000;
destination = destination.subspan(3u);
CHECK(channel_data.Write(base::byte_span_from_ref(
SignedInt32SampleTypeTraits::ToFloat(pcmi))));
}
}
}
#endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
if (CodecSupportsFloatOutput(config_.codec())) {
audio_buffer = AudioBuffer::CopyFrom(
kSampleFormatF32, channel_layout_, channel_count_, sample_rate_, frames,
// Sample format `kSampleFormatF32` is not planar, so it only reads from
// the first pointer in the data array. Thus we give it a pointer to the
// `destination_ptr` and it won't go past it.
&destination_ptr, base::TimeDelta(), pool_);
}
RETURN_ON_FAILURE(!!audio_buffer, "Failed to create output buffer",
OutputStatus::kFailed);
// Important to reset length to 0 since we reuse a same output buffer
output_buffer->SetCurrentLength(0);
output_buffer->Unlock();
if (discard_helper_->ProcessBuffers(current_buffer_time_info_,
audio_buffer.get())) {
base::BindPostTaskToCurrentDefault(output_cb_).Run(std::move(audio_buffer));
}
return OutputStatus::kSuccess;
}
void MediaFoundationAudioDecoder::ResetTimestampState() {
discard_helper_ =
std::make_unique<AudioDiscardHelper>(sample_rate_, config_.codec_delay(),
/*delayed_discard=*/true);
discard_helper_->Reset(config_.codec_delay());
}
} // namespace media