mirror of
https://github.com/Alex313031/thorium.git
synced 2025-01-10 03:47:44 -03:00
M126 stage 6 and update PATCHES.md
This commit is contained in:
parent
eb10d33bdc
commit
9afe5f5d19
16 changed files with 993 additions and 212 deletions
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "components/metrics/machine_id_provider.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
|
|
|
@ -126,4 +126,8 @@ bool DPAPIKeyProvider::UseForEncryption() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DPAPIKeyProvider::IsCompatibleWithOsCryptSync() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace os_crypt_async
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
612
src/media/filters/win/media_foundation_audio_decoder.cc
Normal file
612
src/media/filters/win/media_foundation_audio_decoder.cc
Normal 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, ¤t_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, ¤t_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
|
Loading…
Reference in a new issue