mirror of
https://github.com/Alex313031/thorium.git
synced 2025-01-09 11:27:32 -03:00
add more tab context menu options
This commit is contained in:
parent
ae5aa13c1a
commit
fb07b7f59e
7 changed files with 1042 additions and 2 deletions
|
@ -32,6 +32,9 @@ use_icf = true
|
|||
is_cfi = false
|
||||
v8_symbol_level = 2
|
||||
v8_enable_fast_torque = true
|
||||
# v8_enable_builtins_optimization = true
|
||||
# v8_enable_maglev = true
|
||||
# v8_enable_turbofan = true
|
||||
v8_enable_wasm_simd256_revec = true
|
||||
use_v8_context_snapshot = true
|
||||
blink_symbol_level = 2
|
||||
|
@ -62,7 +65,7 @@ enable_cdm_host_verification = false
|
|||
ignore_missing_widevine_signing_cert = true
|
||||
enable_media_drm_storage = true
|
||||
# enable_media_overlay = true
|
||||
enable_hangout_services_extension = true
|
||||
enable_hangout_services_extension = false
|
||||
rtc_use_h264 = true
|
||||
rtc_include_ilbc = true
|
||||
# rtc_build_with_neon = true
|
||||
|
@ -72,6 +75,7 @@ enable_vr = true
|
|||
# use_vr_assets_component = true
|
||||
enable_platform_hevc = true
|
||||
enable_hevc_parser_and_hw_decoder = true
|
||||
platform_has_optional_hevc_support = true
|
||||
enable_platform_ac3_eac3_audio = true
|
||||
enable_platform_ac4_audio = false
|
||||
enable_platform_dolby_vision = true
|
||||
|
@ -83,4 +87,6 @@ use_text_section_splitting = true
|
|||
use_thin_lto = false
|
||||
thin_lto_enable_optimizations = false
|
||||
enable_rust = true
|
||||
enable_all_rust_features = true
|
||||
# init_stack_vars_zero = true
|
||||
chrome_pgo_phase = 0
|
||||
|
|
|
@ -29,6 +29,9 @@ treat_warnings_as_errors = false
|
|||
use_lld = true
|
||||
v8_symbol_level = 2
|
||||
v8_enable_fast_torque = true
|
||||
# v8_enable_builtins_optimization = true
|
||||
# v8_enable_maglev = true
|
||||
# v8_enable_turbofan = true
|
||||
v8_enable_wasm_simd256_revec = true
|
||||
use_v8_context_snapshot = true
|
||||
blink_symbol_level = 2
|
||||
|
@ -62,7 +65,7 @@ enable_rlz = true
|
|||
ignore_missing_widevine_signing_cert = true
|
||||
enable_media_drm_storage = true
|
||||
# enable_media_overlay = true
|
||||
enable_hangout_services_extension = true
|
||||
enable_hangout_services_extension = false
|
||||
rtc_use_h264 = true
|
||||
rtc_include_ilbc = true
|
||||
# rtc_build_with_neon = true
|
||||
|
@ -72,6 +75,7 @@ enable_vr = true
|
|||
# use_vr_assets_component = true
|
||||
enable_platform_hevc = true
|
||||
enable_hevc_parser_and_hw_decoder = true
|
||||
platform_has_optional_hevc_support = true
|
||||
enable_platform_ac3_eac3_audio = true
|
||||
enable_platform_ac4_audio = false
|
||||
enable_platform_dolby_vision = true
|
||||
|
@ -83,4 +87,6 @@ use_text_section_splitting = true
|
|||
use_thin_lto = false
|
||||
thin_lto_enable_optimizations = false
|
||||
enable_rust = true
|
||||
enable_all_rust_features = true
|
||||
# init_stack_vars_zero = true
|
||||
chrome_pgo_phase = 0
|
||||
|
|
|
@ -206,6 +206,7 @@
|
|||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:chrome/browser/ui/views/tabs/tab_style_views.cc;bpv=1" ADD_DATE="1685601992" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">tab_style_views.cc - Chromium Code Search</A>
|
||||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:chrome/browser/ui/views/tabs/tab_style_views.h;bpv=1" ADD_DATE="1685602008" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">tab_style_views.h - Chromium Code Search</A>
|
||||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:chrome/browser/ui/tabs/tab_strip_model.cc;bpv=1" ADD_DATE="1685602008" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">tab_strip_model.cc - Chromium Code Search</A>
|
||||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:chrome/browser/ui/tabs/tab_strip_model.h;bpv=1" ADD_DATE="1685602008" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">tab_strip_model.h - Chromium Code Search</A>
|
||||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:components/history/core/browser/history_backend.cc;bpv=1" ADD_DATE="1685602056" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">history_backend.cc - Chromium Code Search</A>
|
||||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:chrome/browser/ui/views/frame/browser_root_view.h;bpv=1" ADD_DATE="1685602779" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">browser_root_view.h - Chromium Code Search</A>
|
||||
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/126.0.6478.246:chrome/browser/ui/views/frame/browser_root_view.cc;bpv=1" ADD_DATE="1685602782" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">browser_root_view.cc - Chromium Code Search</A>
|
||||
|
|
|
@ -106,6 +106,23 @@ index d26bc737d3177..f453b459eb3f8 100644
|
|||
// Padding before the tab title.
|
||||
TAB_PRE_TITLE_PADDING,
|
||||
|
||||
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc
|
||||
index bec499693cd91..52e9c7f245110 100644
|
||||
--- a/chrome/browser/ui/tabs/tab_menu_model.cc
|
||||
+++ b/chrome/browser/ui/tabs/tab_menu_model.cc
|
||||
@@ -102,9 +102,9 @@ void TabMenuModel::Build(TabStripModel* tab_strip, int index) {
|
||||
}
|
||||
|
||||
int num_tabs = indices.size();
|
||||
- AddItemWithStringId(TabStripModel::CommandNewTabToRight,
|
||||
- base::i18n::IsRTL() ? IDS_TAB_CXMENU_NEWTABTOLEFT
|
||||
- : IDS_TAB_CXMENU_NEWTABTORIGHT);
|
||||
+ AddItemWithStringId(TabStripModel::CommandNewTabToRight, IDS_TAB_CXMENU_NEWTABTORIGHT);
|
||||
+ AddItemWithStringId(TabStripModel::CommandNewTabToLeft, IDS_TAB_CXMENU_NEWTABTOLEFT);
|
||||
+ AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
|
||||
if (tab_strip->delegate()->SupportsReadLater()) {
|
||||
AddItem(
|
||||
TabStripModel::CommandAddToReadLater,
|
||||
diff --git a/chrome/browser/ui/tabs/tab_style.cc b/chrome/browser/ui/tabs/tab_style.cc
|
||||
index aa9cd30374311..5d5a40f92f922 100644
|
||||
--- a/chrome/browser/ui/tabs/tab_style.cc
|
||||
|
|
|
@ -84,6 +84,10 @@ group("thorium") {
|
|||
if (is_win) {
|
||||
deps += [ "//chrome:chrome_dll" ]
|
||||
}
|
||||
|
||||
if (is_linux || is_chromeos) {
|
||||
deps += [ "//sandbox/linux:chrome_sandbox" ]
|
||||
}
|
||||
}
|
||||
|
||||
# Thorium target that builds everything for a release build
|
||||
|
|
|
@ -1463,6 +1463,7 @@ bool TabStripModel::IsContextMenuCommandEnabled(
|
|||
ContextMenuCommand command_id) const {
|
||||
DCHECK(command_id > CommandFirst && command_id < CommandLast);
|
||||
switch (command_id) {
|
||||
case CommandNewTabToLeft:
|
||||
case CommandNewTabToRight:
|
||||
case CommandCloseTab:
|
||||
return true;
|
||||
|
@ -1574,6 +1575,15 @@ void TabStripModel::ExecuteContextMenuCommand(int context_index,
|
|||
if (!ContainsIndex(context_index))
|
||||
return;
|
||||
switch (command_id) {
|
||||
case CommandNewTabToLeft: {
|
||||
base::RecordAction(UserMetricsAction("TabContextMenu_NewTab"));
|
||||
UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", NewTabTypes::NEW_TAB_CONTEXT_MENU,
|
||||
NewTabTypes::NEW_TAB_ENUM_COUNT);
|
||||
delegate()->AddTabAt(GURL(), context_index - 1, true,
|
||||
GetTabGroupForTab(context_index));
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandNewTabToRight: {
|
||||
base::RecordAction(UserMetricsAction("TabContextMenu_NewTab"));
|
||||
UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", NewTabTypes::NEW_TAB_CONTEXT_MENU,
|
||||
|
|
996
src/chrome/browser/ui/tabs/tab_strip_model.h
Normal file
996
src/chrome/browser/ui/tabs/tab_strip_model.h
Normal file
|
@ -0,0 +1,996 @@
|
|||
// Copyright 2012 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_H_
|
||||
#define CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/span.h"
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/scoped_multi_source_observation.h"
|
||||
#include "base/scoped_observation.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/ui/tabs/tab_group_controller.h"
|
||||
#include "chrome/browser/ui/tabs/tab_model.h"
|
||||
#include "chrome/browser/ui/tabs/tab_strip_collection.h"
|
||||
#include "chrome/browser/ui/tabs/tab_strip_scrubbing_metrics.h"
|
||||
#include "chrome/browser/ui/tabs/tab_strip_user_gesture_details.h"
|
||||
#include "components/sessions/core/session_id.h"
|
||||
#include "components/tab_groups/tab_group_id.h"
|
||||
#include "components/tab_groups/tab_group_visual_data.h"
|
||||
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
|
||||
#include "ui/base/models/list_selection_model.h"
|
||||
#include "ui/base/page_transition_types.h"
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
#error This file should only be included on desktop.
|
||||
#endif
|
||||
|
||||
class Profile;
|
||||
class TabGroupModel;
|
||||
class TabStripModelDelegate;
|
||||
class TabStripModelObserver;
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace tabs {
|
||||
class TabGroupTabCollection;
|
||||
}
|
||||
|
||||
class TabGroupModelFactory {
|
||||
public:
|
||||
TabGroupModelFactory();
|
||||
TabGroupModelFactory(const TabGroupModelFactory&) = delete;
|
||||
TabGroupModelFactory& operator=(const TabGroupModelFactory&) = delete;
|
||||
|
||||
static TabGroupModelFactory* GetInstance();
|
||||
std::unique_ptr<TabGroupModel> Create(TabGroupController* controller);
|
||||
};
|
||||
|
||||
// Holds state for a WebContents that has been detached from the tab strip.
|
||||
// Will also handle WebContents deletion if |remove_reason| is kDeleted, or
|
||||
// WebContents caching if |remove_reason| is kCached.
|
||||
struct DetachedWebContents {
|
||||
DetachedWebContents(int index_before_any_removals,
|
||||
int index_at_time_of_removal,
|
||||
std::unique_ptr<tabs::TabModel> tab,
|
||||
content::WebContents* contents,
|
||||
TabStripModelChange::RemoveReason remove_reason,
|
||||
std::optional<SessionID> id);
|
||||
DetachedWebContents(const DetachedWebContents&) = delete;
|
||||
DetachedWebContents& operator=(const DetachedWebContents&) = delete;
|
||||
~DetachedWebContents();
|
||||
DetachedWebContents(DetachedWebContents&&);
|
||||
|
||||
// When a WebContents is removed the delegate is given a chance to
|
||||
// take ownership of it (generally for caching). If the delegate takes
|
||||
// ownership, `tab` will be null, and `contents` will be
|
||||
// non-null. In other words, all observers should use `contents`, it is
|
||||
// guaranteed to be valid for the life time of the notification (and
|
||||
// possibly longer).
|
||||
std::unique_ptr<tabs::TabModel> tab;
|
||||
raw_ptr<content::WebContents, AcrossTasksDanglingUntriaged> contents;
|
||||
|
||||
// The index of the WebContents in the original selection model of the tab
|
||||
// strip [prior to any tabs being removed, if multiple tabs are being
|
||||
// simultaneously removed].
|
||||
const int index_before_any_removals;
|
||||
|
||||
// The index of the WebContents at the time it is being removed. If multiple
|
||||
// tabs are being simultaneously removed, the index reflects previously
|
||||
// removed tabs in this batch.
|
||||
const int index_at_time_of_removal;
|
||||
|
||||
TabStripModelChange::RemoveReason remove_reason;
|
||||
|
||||
// The |contents| associated optional SessionID, used as key for
|
||||
// ClosedTabCache. We only cache |contents| if |remove_reason| is kCached.
|
||||
std::optional<SessionID> id;
|
||||
};
|
||||
|
||||
// A feature which wants to show tabstrip-modal UI should call
|
||||
// TabStripController::ShowModalUI and keep alive the instance of
|
||||
// ScopedTabStripModalUI for the duration of the tabstrip-modal UI.
|
||||
class ScopedTabStripModalUI {
|
||||
public:
|
||||
ScopedTabStripModalUI() = default;
|
||||
virtual ~ScopedTabStripModalUI() = default;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TabStripModel
|
||||
//
|
||||
// A model & low level controller of a Browser Window tabstrip. Holds a vector
|
||||
// of WebContents, and provides an API for adding, removing and
|
||||
// shuffling them, as well as a higher level API for doing specific Browser-
|
||||
// related tasks like adding new Tabs from just a URL, etc.
|
||||
//
|
||||
// Each tab may be pinned. Pinned tabs are locked to the left side of the tab
|
||||
// strip and rendered differently (small tabs with only a favicon). The model
|
||||
// makes sure all pinned tabs are at the beginning of the tab strip. For
|
||||
// example, if a non-pinned tab is added it is forced to be with non-pinned
|
||||
// tabs. Requests to move tabs outside the range of the tab type are ignored.
|
||||
// For example, a request to move a pinned tab after non-pinned tabs is ignored.
|
||||
//
|
||||
// A TabStripModel has one delegate that it relies on to perform certain tasks
|
||||
// like creating new TabStripModels (probably hosted in Browser windows) when
|
||||
// required. See TabStripDelegate above for more information.
|
||||
//
|
||||
// A TabStripModel also has N observers (see TabStripModelObserver above),
|
||||
// which can be registered via Add/RemoveObserver. An Observer is notified of
|
||||
// tab creations, removals, moves, and other interesting events. The
|
||||
// TabStrip implements this interface to know when to create new tabs in
|
||||
// the View, and the Browser object likewise implements to be able to update
|
||||
// its bookkeeping when such events happen.
|
||||
//
|
||||
// This implementation of TabStripModel is not thread-safe and should only be
|
||||
// accessed on the UI thread.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class TabStripModel : public TabGroupController {
|
||||
public:
|
||||
// TODO(crbug.com/40881446): Remove this, and use std::optional<size_t> (or at
|
||||
// least std::optional<int>) in its place.
|
||||
static constexpr int kNoTab = -1;
|
||||
|
||||
using TabDataVariant =
|
||||
std::variant<std::vector<std::unique_ptr<tabs::TabModel>>,
|
||||
std::unique_ptr<tabs::TabStripCollection>>;
|
||||
|
||||
TabStripModel() = delete;
|
||||
|
||||
// Construct a TabStripModel with a delegate to help it do certain things
|
||||
// (see the TabStripModelDelegate documentation). |delegate| cannot be NULL.
|
||||
// the TabGroupModelFactory can be replaced with a nullptr to set the
|
||||
// group_model to null in cases where groups are not supported.
|
||||
explicit TabStripModel(TabStripModelDelegate* delegate,
|
||||
Profile* profile,
|
||||
TabGroupModelFactory* group_model_factory =
|
||||
TabGroupModelFactory::GetInstance());
|
||||
|
||||
TabStripModel(const TabStripModel&) = delete;
|
||||
TabStripModel& operator=(const TabStripModel&) = delete;
|
||||
|
||||
~TabStripModel() override;
|
||||
|
||||
// Retrieves the TabStripModelDelegate associated with this TabStripModel.
|
||||
TabStripModelDelegate* delegate() const { return delegate_; }
|
||||
|
||||
// Sets the TabStripModelObserver used by the UI showing the tabs. As other
|
||||
// observers may query the UI for state, the UI's observer must be first.
|
||||
void SetTabStripUI(TabStripModelObserver* observer);
|
||||
|
||||
// Add and remove observers to changes within this TabStripModel.
|
||||
void AddObserver(TabStripModelObserver* observer);
|
||||
void RemoveObserver(TabStripModelObserver* observer);
|
||||
|
||||
// Retrieve the number of WebContentses/emptiness of the TabStripModel.
|
||||
int count() const;
|
||||
bool empty() const;
|
||||
|
||||
int GetIndexOfTab(tabs::TabHandle tab) const;
|
||||
tabs::TabHandle GetTabHandleAt(int index) const;
|
||||
|
||||
// Returns true if the data is a vector and not a collection tree.
|
||||
bool IsContentsDataVector() const {
|
||||
return std::holds_alternative<std::vector<std::unique_ptr<tabs::TabModel>>>(
|
||||
contents_data_);
|
||||
}
|
||||
|
||||
// const methods to access `contents_data_` as a vector or a collection tree.
|
||||
const std::vector<std::unique_ptr<tabs::TabModel>>& GetContentsDataAsVector()
|
||||
const;
|
||||
const tabs::TabStripCollection* GetContentsDataAsCollection() const;
|
||||
|
||||
// non-const methods to access `contents_data_` as a vector or a collection
|
||||
// tree.
|
||||
std::vector<std::unique_ptr<tabs::TabModel>>& GetContentsDataAsVector();
|
||||
tabs::TabStripCollection* GetContentsDataAsCollection();
|
||||
|
||||
// Retrieve the Profile associated with this TabStripModel.
|
||||
Profile* profile() const { return profile_; }
|
||||
|
||||
// Retrieve the index of the currently active WebContents. The only time this
|
||||
// is kNoTab is if the tab strip is being initialized or destroyed. Note that
|
||||
// tab strip destruction is an asynchronous process.
|
||||
int active_index() const {
|
||||
return selection_model_.active().has_value()
|
||||
? static_cast<int>(selection_model_.active().value())
|
||||
: kNoTab;
|
||||
}
|
||||
|
||||
// Returns true if the tabstrip is currently closing all open tabs (via a
|
||||
// call to CloseAllTabs). As tabs close, the selection in the tabstrip
|
||||
// changes which notifies observers, which can use this as an optimization to
|
||||
// avoid doing meaningless or unhelpful work.
|
||||
bool closing_all() const { return closing_all_; }
|
||||
|
||||
// Basic API /////////////////////////////////////////////////////////////////
|
||||
|
||||
// Determines if the specified index is contained within the TabStripModel.
|
||||
bool ContainsIndex(int index) const;
|
||||
|
||||
// Adds the specified WebContents in the default location. Tabs opened
|
||||
// in the foreground inherit the opener of the previously active tab.
|
||||
// Use of the detached tab is preferred over webcontents, so when possible
|
||||
// use AppendTab instead of this method.
|
||||
void AppendWebContents(std::unique_ptr<content::WebContents> contents,
|
||||
bool foreground);
|
||||
|
||||
// Adds the specified Tab at the end of the Tabstrip. Tabs opened
|
||||
// in the foreground inherit the opener of the previously active tab and
|
||||
// become the active tab.
|
||||
void AppendTab(std::unique_ptr<tabs::TabModel> tab, bool foreground);
|
||||
|
||||
// Adds the specified WebContents at the specified location.
|
||||
// |add_types| is a bitmask of AddTabTypes; see it for details.
|
||||
//
|
||||
// All append/insert methods end up in this method.
|
||||
//
|
||||
// NOTE: adding a tab using this method does NOT query the order controller,
|
||||
// as such the ADD_FORCE_INDEX AddTabTypes is meaningless here. The only time
|
||||
// the |index| is changed is if using the index would result in breaking the
|
||||
// constraint that all pinned tabs occur before non-pinned tabs. It returns
|
||||
// the index the web contents is actually inserted to. See also
|
||||
// AddWebContents.
|
||||
int InsertWebContentsAt(
|
||||
int index,
|
||||
std::unique_ptr<content::WebContents> contents,
|
||||
int add_types,
|
||||
std::optional<tab_groups::TabGroupId> group = std::nullopt);
|
||||
|
||||
// Adds a TabModel from another tabstrip at the specified location. See
|
||||
// InsertWebContentsAt.
|
||||
int InsertDetachedTabAt(
|
||||
int index,
|
||||
std::unique_ptr<tabs::TabModel> tab,
|
||||
int add_types,
|
||||
std::optional<tab_groups::TabGroupId> group = std::nullopt);
|
||||
|
||||
// Closes the WebContents at the specified index. This causes the
|
||||
// WebContents to be destroyed, but it may not happen immediately.
|
||||
// |close_types| is a bitmask of CloseTypes.
|
||||
void CloseWebContentsAt(int index, uint32_t close_types);
|
||||
|
||||
// Discards the WebContents at |index| and replaces it with |new_contents|.
|
||||
// The WebContents that was at |index| is returned and its ownership returns
|
||||
// to the caller.
|
||||
std::unique_ptr<content::WebContents> DiscardWebContentsAt(
|
||||
int index,
|
||||
std::unique_ptr<content::WebContents> new_contents);
|
||||
|
||||
// Detaches the tab at the specified index for reinsertion into another tab
|
||||
// strip. Returns the detached tab.
|
||||
std::unique_ptr<tabs::TabModel> DetachTabAtForInsertion(int index);
|
||||
|
||||
// Detaches the WebContents at the specified index and immediately deletes it.
|
||||
void DetachAndDeleteWebContentsAt(int index);
|
||||
|
||||
// Makes the tab at the specified index the active tab. |gesture_detail.type|
|
||||
// contains the gesture type that triggers the tab activation.
|
||||
// |gesture_detail.time_stamp| contains the timestamp of the user gesture, if
|
||||
// any.
|
||||
void ActivateTabAt(
|
||||
int index,
|
||||
TabStripUserGestureDetails gesture_detail = TabStripUserGestureDetails(
|
||||
TabStripUserGestureDetails::GestureType::kNone));
|
||||
|
||||
// Move the WebContents at the specified index to another index. This
|
||||
// method does NOT send Detached/Attached notifications, rather it moves the
|
||||
// WebContents inline and sends a Moved notification instead.
|
||||
// EnsureGroupContiguity() is called after the move, so this will never result
|
||||
// in non-contiguous group (though the moved tab's group may change).
|
||||
// If |select_after_move| is false, whatever tab was selected before the move
|
||||
// will still be selected, but its index may have incremented or decremented
|
||||
// one slot. It returns the index the web contents is actually moved to.
|
||||
int MoveWebContentsAt(int index, int to_position, bool select_after_move);
|
||||
|
||||
// Moves the selected tabs to |index|. |index| is treated as if the tab strip
|
||||
// did not contain any of the selected tabs. For example, if the tabstrip
|
||||
// contains [A b c D E f] (upper case selected) and this is invoked with 1 the
|
||||
// result is [b A D E c f].
|
||||
// This method maintains that all pinned tabs occur before non-pinned tabs.
|
||||
// When pinned tabs are selected the move is processed in two chunks: first
|
||||
// pinned tabs are moved, then non-pinned tabs are moved. If the index is
|
||||
// after (pinned-tab-count - selected-pinned-tab-count), then the index the
|
||||
// non-pinned selected tabs are moved to is (index +
|
||||
// selected-pinned-tab-count). For example, if the model consists of
|
||||
// [A b c D E f] (A b c are pinned) and this is invoked with 2, the result is
|
||||
// [b c A D E f]. In this example nothing special happened because the target
|
||||
// index was <= (pinned-tab-count - selected-pinned-tab-count). If the target
|
||||
// index were 3, then the result would be [b c A f D F]. A, being pinned, can
|
||||
// move no further than index 2. The non-pinned tabs are moved to the target
|
||||
// index + selected-pinned tab-count (3 + 1).
|
||||
void MoveSelectedTabsTo(int index);
|
||||
|
||||
// Moves all tabs in |group| to |to_index|. This has no checks to make sure
|
||||
// the position is valid for a group to move to.
|
||||
void MoveGroupTo(const tab_groups::TabGroupId& group, int to_index);
|
||||
|
||||
// Returns the currently active WebContents, or NULL if there is none.
|
||||
content::WebContents* GetActiveWebContents() const;
|
||||
|
||||
// Returns the currently active Tab, or NULL if there is none.
|
||||
tabs::TabModel* GetActiveTab() const;
|
||||
|
||||
// Returns the WebContents at the specified index, or NULL if there is
|
||||
// none.
|
||||
content::WebContents* GetWebContentsAt(int index) const;
|
||||
|
||||
// Returns the index of the specified WebContents, or TabStripModel::kNoTab
|
||||
// if the WebContents is not in this TabStripModel.
|
||||
int GetIndexOfWebContents(const content::WebContents* contents) const;
|
||||
|
||||
// Notify any observers that the WebContents at the specified index has
|
||||
// changed in some way. See TabChangeType for details of |change_type|.
|
||||
void UpdateWebContentsStateAt(int index, TabChangeType change_type);
|
||||
|
||||
// Cause a tab to display a UI indication to the user that it needs their
|
||||
// attention.
|
||||
void SetTabNeedsAttentionAt(int index, bool attention);
|
||||
|
||||
// Close all tabs at once. Code can use closing_all() above to defer
|
||||
// operations that might otherwise by invoked by the flurry of detach/select
|
||||
// notifications this method causes.
|
||||
void CloseAllTabs();
|
||||
|
||||
// Close all tabs in the given |group| at once.
|
||||
void CloseAllTabsInGroup(const tab_groups::TabGroupId& group);
|
||||
|
||||
// Returns true if there are any WebContentses that are currently loading.
|
||||
bool TabsAreLoading() const;
|
||||
|
||||
// Returns the WebContents that opened the WebContents at |index|, or NULL if
|
||||
// there is no opener on record.
|
||||
content::WebContents* GetOpenerOfWebContentsAt(const int index) const;
|
||||
|
||||
// Changes the |opener| of the WebContents at |index|.
|
||||
// Note: |opener| must be in this tab strip. Also a tab must not be its own
|
||||
// opener.
|
||||
void SetOpenerOfWebContentsAt(int index, content::WebContents* opener);
|
||||
|
||||
// Returns the index of the last WebContents in the model opened by the
|
||||
// specified opener, starting at |start_index|.
|
||||
int GetIndexOfLastWebContentsOpenedBy(const content::WebContents* opener,
|
||||
int start_index) const;
|
||||
|
||||
// To be called when a navigation is about to occur in the specified
|
||||
// WebContents. Depending on the tab, and the transition type of the
|
||||
// navigation, the TabStripModel may adjust its selection behavior and opener
|
||||
// inheritance.
|
||||
void TabNavigating(content::WebContents* contents,
|
||||
ui::PageTransition transition);
|
||||
|
||||
// Changes the blocked state of the tab at |index|.
|
||||
void SetTabBlocked(int index, bool blocked);
|
||||
|
||||
// Changes the pinned state of the tab at `index`. See description above
|
||||
// class for details on this. Returns the index the tab is now at (it may have
|
||||
// been moved to maintain contiguity of pinned tabs at the beginning of the
|
||||
// tabstrip).)
|
||||
int SetTabPinned(int index, bool pinned);
|
||||
|
||||
// Returns true if the tab at |index| is pinned.
|
||||
// See description above class for details on pinned tabs.
|
||||
bool IsTabPinned(int index) const;
|
||||
|
||||
bool IsTabCollapsed(int index) const;
|
||||
|
||||
bool IsGroupCollapsed(const tab_groups::TabGroupId& group) const;
|
||||
|
||||
// Returns true if the tab at |index| is blocked by a tab modal dialog.
|
||||
bool IsTabBlocked(int index) const;
|
||||
|
||||
// Returns true if the tab at |index| is allowed to be closed.
|
||||
bool IsTabClosable(int index) const;
|
||||
|
||||
// Returns true if the tab corresponding to |contents| is allowed to be
|
||||
// closed.
|
||||
bool IsTabClosable(const content::WebContents* contents) const;
|
||||
|
||||
// Returns the group that contains the tab at |index|, or nullopt if the tab
|
||||
// index is invalid or not grouped.
|
||||
std::optional<tab_groups::TabGroupId> GetTabGroupForTab(
|
||||
int index) const override;
|
||||
|
||||
// If a tab inserted at |index| would be within a tab group, return that
|
||||
// group's ID. Otherwise, return nullopt. If |index| points to the first tab
|
||||
// in a group, it will return nullopt since a new tab would be either between
|
||||
// two different groups or just after a non-grouped tab.
|
||||
std::optional<tab_groups::TabGroupId> GetSurroundingTabGroup(int index) const;
|
||||
|
||||
// Returns the index of the first tab that is not a pinned tab. This returns
|
||||
// |count()| if all of the tabs are pinned tabs, and 0 if none of the tabs are
|
||||
// pinned tabs.
|
||||
int IndexOfFirstNonPinnedTab() const;
|
||||
|
||||
// Extends the selection from the anchor to |index|.
|
||||
void ExtendSelectionTo(int index);
|
||||
|
||||
// Returns true if the selection was toggled; this can fail if the tabstrip
|
||||
// is not editable.
|
||||
bool ToggleSelectionAt(int index);
|
||||
|
||||
// Makes sure the tabs from the anchor to |index| are selected. This only
|
||||
// adds to the selection.
|
||||
void AddSelectionFromAnchorTo(int index);
|
||||
|
||||
// Returns true if the tab at |index| is selected.
|
||||
bool IsTabSelected(int index) const;
|
||||
|
||||
// Returns the timestamp at which the tab was last accessed.
|
||||
std::optional<base::Time> GetLastAccessed(int index) const;
|
||||
|
||||
// Sets the selection to match that of |source|.
|
||||
void SetSelectionFromModel(ui::ListSelectionModel source);
|
||||
|
||||
const ui::ListSelectionModel& selection_model() const;
|
||||
|
||||
// Features that want to show tabstrip-modal UI are mutually exclusive.
|
||||
// Before showing a modal UI first check `CanShowModalUI`. Then call
|
||||
// ShowModalUI() and keep `ScopedTabStripModal` alive to prevent other
|
||||
// features from showing tabstrip-modal UI.
|
||||
bool CanShowModalUI() const;
|
||||
std::unique_ptr<ScopedTabStripModalUI> ShowModalUI();
|
||||
|
||||
// Command level API /////////////////////////////////////////////////////////
|
||||
|
||||
// Adds a WebContents at the best position in the TabStripModel given
|
||||
// the specified insertion index, transition, etc. |add_types| is a bitmask of
|
||||
// AddTabTypes; see it for details. This method ends up calling into
|
||||
// InsertWebContentsAt to do the actual insertion. Pass kNoTab for |index| to
|
||||
// append the contents to the end of the tab strip.
|
||||
void AddWebContents(
|
||||
std::unique_ptr<content::WebContents> contents,
|
||||
int index,
|
||||
ui::PageTransition transition,
|
||||
int add_types,
|
||||
std::optional<tab_groups::TabGroupId> group = std::nullopt);
|
||||
|
||||
// Closes the selected tabs.
|
||||
void CloseSelectedTabs();
|
||||
|
||||
// Select adjacent tabs
|
||||
void SelectNextTab(
|
||||
TabStripUserGestureDetails detail = TabStripUserGestureDetails(
|
||||
TabStripUserGestureDetails::GestureType::kOther));
|
||||
void SelectPreviousTab(
|
||||
TabStripUserGestureDetails detail = TabStripUserGestureDetails(
|
||||
TabStripUserGestureDetails::GestureType::kOther));
|
||||
|
||||
// Selects the last tab in the tab strip.
|
||||
void SelectLastTab(
|
||||
TabStripUserGestureDetails detail = TabStripUserGestureDetails(
|
||||
TabStripUserGestureDetails::GestureType::kOther));
|
||||
|
||||
// Moves the active in the specified direction. Respects group boundaries.
|
||||
void MoveTabNext();
|
||||
void MoveTabPrevious();
|
||||
|
||||
// Create a new tab group and add the set of tabs pointed to be |indices| to
|
||||
// it. Pins all of the tabs if any of them were pinned, and reorders the tabs
|
||||
// so they are contiguous and do not split an existing group in half. Returns
|
||||
// the new group. |indices| must be sorted in ascending order.
|
||||
tab_groups::TabGroupId AddToNewGroup(const std::vector<int>& indices);
|
||||
|
||||
// Add the set of tabs pointed to by |indices| to the given tab group |group|.
|
||||
// The tabs take on the pinnedness of the tabs already in the group. Tabs
|
||||
// before the group will move to the start, while tabs after the group will
|
||||
// move to the end. If |add_to_end| is true, all tabs will instead move to
|
||||
// the end. |indices| must be sorted in ascending order.
|
||||
void AddToExistingGroup(const std::vector<int>& indices,
|
||||
const tab_groups::TabGroupId& group,
|
||||
const bool add_to_end = false);
|
||||
|
||||
// Moves the set of tabs indicated by |indices| to precede the tab at index
|
||||
// |destination_index|, maintaining their order and the order of tabs not
|
||||
// being moved, and adds them to the tab group |group|.
|
||||
void MoveTabsAndSetGroup(const std::vector<int>& indices,
|
||||
int destination_index,
|
||||
std::optional<tab_groups::TabGroupId> group);
|
||||
|
||||
// Similar to AddToExistingGroup(), but creates a group with id |group| if it
|
||||
// doesn't exist. This is only intended to be called from session restore
|
||||
// code.
|
||||
void AddToGroupForRestore(const std::vector<int>& indices,
|
||||
const tab_groups::TabGroupId& group);
|
||||
|
||||
// Updates the tab group of the tab at |index|. If |group| is nullopt, the tab
|
||||
// will be removed from the current group. If |group| does not exist, it will
|
||||
// create the group then add the tab to the group.
|
||||
void UpdateGroupForDragRevert(
|
||||
int index,
|
||||
std::optional<tab_groups::TabGroupId> group_id,
|
||||
std::optional<tab_groups::TabGroupVisualData> group_data);
|
||||
|
||||
// Removes the set of tabs pointed to by |indices| from the the groups they
|
||||
// are in, if any. The tabs are moved out of the group if necessary. |indices|
|
||||
// must be sorted in ascending order.
|
||||
void RemoveFromGroup(std::vector<int> indices);
|
||||
|
||||
TabGroupModel* group_model() const { return group_model_.get(); }
|
||||
|
||||
bool SupportsTabGroups() const { return group_model_.get() != nullptr; }
|
||||
|
||||
// Returns true if one or more of the tabs pointed to by |indices| are
|
||||
// supported by read later.
|
||||
bool IsReadLaterSupportedForAny(const std::vector<int>& indices);
|
||||
|
||||
// Saves tabs with url supported by Read Later.
|
||||
void AddToReadLater(const std::vector<int>& indices);
|
||||
|
||||
// TabGroupController:
|
||||
void CreateTabGroup(const tab_groups::TabGroupId& group) override;
|
||||
void OpenTabGroupEditor(const tab_groups::TabGroupId& group) override;
|
||||
void ChangeTabGroupContents(const tab_groups::TabGroupId& group) override;
|
||||
void ChangeTabGroupVisuals(
|
||||
const tab_groups::TabGroupId& group,
|
||||
const TabGroupChange::VisualsChange& visuals) override;
|
||||
void MoveTabGroup(const tab_groups::TabGroupId& group) override;
|
||||
void CloseTabGroup(const tab_groups::TabGroupId& group) override;
|
||||
std::u16string GetTitleAt(int index) const override;
|
||||
// The same as count(), but overridden for TabGroup to access.
|
||||
int GetTabCount() const override;
|
||||
|
||||
// View API //////////////////////////////////////////////////////////////////
|
||||
|
||||
// Context menu functions. Tab groups uses command ids following CommandLast
|
||||
// for entries in the 'Add to existing group' submenu.
|
||||
enum ContextMenuCommand {
|
||||
CommandFirst,
|
||||
CommandNewTabToLeft,
|
||||
CommandNewTabToRight,
|
||||
CommandReload,
|
||||
CommandDuplicate,
|
||||
CommandCloseTab,
|
||||
CommandCloseOtherTabs,
|
||||
CommandCloseTabsToRight,
|
||||
CommandTogglePinned,
|
||||
CommandToggleGrouped,
|
||||
CommandToggleSiteMuted,
|
||||
CommandSendTabToSelf,
|
||||
CommandAddNote,
|
||||
CommandAddToReadLater,
|
||||
CommandAddToNewGroup,
|
||||
CommandAddToExistingGroup,
|
||||
CommandRemoveFromGroup,
|
||||
CommandMoveToExistingWindow,
|
||||
CommandMoveTabsToNewWindow,
|
||||
CommandOrganizeTabs,
|
||||
CommandCopyURL,
|
||||
CommandGoBack,
|
||||
CommandCloseAllTabs,
|
||||
CommandCommerceProductSpecifications,
|
||||
CommandLast
|
||||
};
|
||||
|
||||
// Returns true if the specified command is enabled. If |context_index| is
|
||||
// selected the response applies to all selected tabs.
|
||||
bool IsContextMenuCommandEnabled(int context_index,
|
||||
ContextMenuCommand command_id) const;
|
||||
|
||||
// Performs the action associated with the specified command for the given
|
||||
// TabStripModel index |context_index|. If |context_index| is selected the
|
||||
// command applies to all selected tabs.
|
||||
void ExecuteContextMenuCommand(int context_index,
|
||||
ContextMenuCommand command_id);
|
||||
|
||||
// Returns a list of the group ids that are going to be deleted if a given
|
||||
// list of tab indexes are removed from the group. used by context menu
|
||||
// commands to decide whether to confirm group deletion.
|
||||
std::vector<tab_groups::TabGroupId> GetGroupsDestroyedFromRemovingIndices(
|
||||
const std::vector<int>& indices) const;
|
||||
|
||||
// There are multiple commands that close by indices. They all must check the
|
||||
// Group affiliation of the indices, confirm that they can delete groups, and
|
||||
// then perform the close of the indices.
|
||||
void ExecuteCloseTabsByIndicesCommand(
|
||||
const std::vector<int>& indices_to_delete);
|
||||
|
||||
// Adds the tab at |context_index| to the given tab group |group|. If
|
||||
// |context_index| is selected the command applies to all selected tabs.
|
||||
void ExecuteAddToExistingGroupCommand(int context_index,
|
||||
const tab_groups::TabGroupId& group);
|
||||
|
||||
// Adds the tab at |context_index| to the browser window at |browser_index|.
|
||||
// If |context_index| is selected the command applies to all selected tabs.
|
||||
void ExecuteAddToExistingWindowCommand(int context_index, int browser_index);
|
||||
|
||||
// Returns true if 'CommandToggleSiteMuted' will mute. |index| is the
|
||||
// index supplied to |ExecuteContextMenuCommand|.
|
||||
bool WillContextMenuMuteSites(int index);
|
||||
|
||||
// Returns true if 'CommandTogglePinned' will pin. |index| is the index
|
||||
// supplied to |ExecuteContextMenuCommand|.
|
||||
bool WillContextMenuPin(int index);
|
||||
|
||||
// Returns true if 'CommandToggleGrouped' will group. |index| is the index
|
||||
// supplied to |ExecuteContextMenuCommand|.
|
||||
bool WillContextMenuGroup(int index);
|
||||
|
||||
// Convert a ContextMenuCommand into a browser command. Returns true if a
|
||||
// corresponding browser command exists, false otherwise.
|
||||
static bool ContextMenuCommandToBrowserCommand(int cmd_id, int* browser_cmd);
|
||||
|
||||
// Returns the index of the next WebContents in the sequence of WebContentses
|
||||
// spawned by the specified WebContents after |start_index|.
|
||||
int GetIndexOfNextWebContentsOpenedBy(const content::WebContents* opener,
|
||||
int start_index) const;
|
||||
|
||||
// Finds the next available tab to switch to as the active tab starting at
|
||||
// |index|. This method will check the indices to the right of |index| before
|
||||
// checking the indices to the left of |index|. |index| cannot be returned.
|
||||
// |collapsing_group| is optional and used in cases where the group is
|
||||
// collapsing but not yet reflected in the model. Returns std::nullopt if
|
||||
// there are no valid tabs.
|
||||
std::optional<int> GetNextExpandedActiveTab(
|
||||
int index,
|
||||
std::optional<tab_groups::TabGroupId> collapsing_group) const;
|
||||
|
||||
// Forget all opener relationships, to reduce unpredictable tab switching
|
||||
// behavior in complex session states.
|
||||
void ForgetAllOpeners();
|
||||
|
||||
// Forgets the opener relationship of the specified WebContents.
|
||||
void ForgetOpener(content::WebContents* contents);
|
||||
|
||||
// Determine where to place a newly opened tab by using the supplied
|
||||
// transition and foreground flag to figure out how it was opened.
|
||||
int DetermineInsertionIndex(ui::PageTransition transition, bool foreground);
|
||||
|
||||
// If a tab is in a group and the tab failed to close, this method will be
|
||||
// called from the unload_controller. Ungroup the group to maintain
|
||||
// consistency with the user's intended action (to get rid of the group).
|
||||
void GroupCloseStopped(const tab_groups::TabGroupId& group);
|
||||
|
||||
// Serialise this object into a trace.
|
||||
void WriteIntoTrace(perfetto::TracedValue context) const;
|
||||
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(TabStripModelTest, GetIndicesClosedByCommand);
|
||||
|
||||
struct DetachNotifications;
|
||||
|
||||
// Tracks whether a tabstrip-modal UI is showing.
|
||||
class ScopedTabStripModalUIImpl : public ScopedTabStripModalUI {
|
||||
public:
|
||||
explicit ScopedTabStripModalUIImpl(TabStripModel* model);
|
||||
~ScopedTabStripModalUIImpl() override;
|
||||
|
||||
private:
|
||||
// Owns this.
|
||||
raw_ptr<TabStripModel> model_;
|
||||
};
|
||||
|
||||
// Perform tasks associated with changes to the model. Change the Active Index
|
||||
// and notify observers.
|
||||
void OnChange(const TabStripModelChange& change,
|
||||
const TabStripSelectionChange& selection);
|
||||
|
||||
// Detaches the WebContents at the specified |index| from this strip. |reason|
|
||||
// is used to indicate to observers what is going to happen to the WebContents
|
||||
// (i.e. deleted or reinserted into another tab strip). Returns the detached
|
||||
// WebContents.
|
||||
std::unique_ptr<DetachedWebContents> DetachWebContentsWithReasonAt(
|
||||
int index,
|
||||
TabStripModelChange::RemoveReason reason);
|
||||
|
||||
// Performs all the work to detach a WebContents instance but avoids sending
|
||||
// most notifications. TabClosingAt() and TabDetachedAt() are sent because
|
||||
// observers are reliant on the selection model being accurate at the time
|
||||
// that TabDetachedAt() is called.
|
||||
std::unique_ptr<DetachedWebContents> DetachWebContentsImpl(
|
||||
int index_before_any_removals,
|
||||
int index_at_time_of_removal,
|
||||
bool create_historical_tab,
|
||||
TabStripModelChange::RemoveReason reason);
|
||||
|
||||
// We batch send notifications. This has two benefits:
|
||||
// 1) This allows us to send the minimal number of necessary notifications.
|
||||
// This is important because some notifications cause the main thread to
|
||||
// synchronously communicate with the GPU process and cause jank.
|
||||
// https://crbug.com/826287.
|
||||
// 2) This allows us to avoid some problems caused by re-entrancy [e.g.
|
||||
// using destroyed WebContents instances]. Ideally, this second check
|
||||
// wouldn't be necessary because we would enforce that there is no
|
||||
// re-entrancy in the TabStripModel, but that condition is currently
|
||||
// violated in tests [and possibly in the wild as well].
|
||||
void SendDetachWebContentsNotifications(DetachNotifications* notifications);
|
||||
|
||||
bool RunUnloadListenerBeforeClosing(content::WebContents* contents);
|
||||
bool ShouldRunUnloadListenerBeforeClosing(content::WebContents* contents);
|
||||
|
||||
int ConstrainInsertionIndex(int index, bool pinned_tab) const;
|
||||
|
||||
int ConstrainMoveIndex(int index, bool pinned_tab) const;
|
||||
|
||||
// Returns the tab at an index from the `contents_data`.
|
||||
tabs::TabModel* GetTabAtIndex(int index) const;
|
||||
|
||||
// If |index| is selected all the selected indices are returned, otherwise a
|
||||
// vector with |index| is returned. This is used when executing commands to
|
||||
// determine which indices the command applies to. Indices are sorted in
|
||||
// increasing order.
|
||||
std::vector<int> GetIndicesForCommand(int index) const;
|
||||
|
||||
// Returns a vector of indices of the tabs that will close when executing the
|
||||
// command |id| for the tab at |index|. The returned indices are sorted in
|
||||
// descending order.
|
||||
std::vector<int> GetIndicesClosedByCommand(int index,
|
||||
ContextMenuCommand id) const;
|
||||
|
||||
// Returns true if the specified WebContents is a New Tab at the end of
|
||||
// the tabstrip. We check for this because opener relationships are _not_
|
||||
// forgotten for the New Tab page opened as a result of a New Tab gesture
|
||||
// (e.g. Ctrl+T, etc) since the user may open a tab transiently to look up
|
||||
// something related to their current activity.
|
||||
bool IsNewTabAtEndOfTabStrip(content::WebContents* contents) const;
|
||||
|
||||
// Adds the specified TabModel at the specified location.
|
||||
// |add_types| is a bitmask of AddTabTypes; see it for details.
|
||||
//
|
||||
// All append/insert methods end up in this method.
|
||||
//
|
||||
// NOTE: adding a tab using this method does NOT query the order controller,
|
||||
// as such the ADD_FORCE_INDEX AddTabTypes is meaningless here. The only time
|
||||
// the |index| is changed is if using the index would result in breaking the
|
||||
// constraint that all pinned tabs occur before non-pinned tabs. It returns
|
||||
// the index the tab is actually inserted to. See also AddWebContents.
|
||||
int InsertTabAtImpl(int index,
|
||||
std::unique_ptr<tabs::TabModel> tab,
|
||||
int add_types,
|
||||
std::optional<tab_groups::TabGroupId> group);
|
||||
|
||||
// Closes the WebContentses at the specified indices. This causes the
|
||||
// WebContentses to be destroyed, but it may not happen immediately. If
|
||||
// the page in question has an unload event the WebContents will not be
|
||||
// destroyed until after the event has completed, which will then call back
|
||||
// into this method.
|
||||
void CloseTabs(base::span<content::WebContents* const> items,
|
||||
uint32_t close_types);
|
||||
|
||||
// |close_types| is a bitmask of the types in CloseTypes.
|
||||
// Returns true if all the tabs have been deleted. A return value of false
|
||||
// means some portion (potentially none) of the WebContents were deleted.
|
||||
// WebContents not deleted by this function are processing unload handlers
|
||||
// which may eventually be deleted based on the results of the unload handler.
|
||||
// Additionally processing the unload handlers may result in needing to show
|
||||
// UI for the WebContents. See UnloadController for details on how unload
|
||||
// handlers are processed.
|
||||
bool CloseWebContentses(base::span<content::WebContents* const> items,
|
||||
uint32_t close_types,
|
||||
DetachNotifications* notifications);
|
||||
|
||||
// Gets the WebContents at an index. Does no bounds checking.
|
||||
content::WebContents* GetWebContentsAtImpl(int index) const;
|
||||
|
||||
// Returns the WebContentses at the specified indices. This does no checking
|
||||
// of the indices, it is assumed they are valid.
|
||||
std::vector<content::WebContents*> GetWebContentsesByIndices(
|
||||
const std::vector<int>& indices) const;
|
||||
|
||||
// Sets the selection to |new_model| and notifies any observers.
|
||||
// Note: This function might end up sending 0 to 3 notifications in the
|
||||
// following order: TabDeactivated, ActiveTabChanged, TabSelectionChanged.
|
||||
// |selection| will be filled with information corresponding to 3 notification
|
||||
// above. When it's |triggered_by_other_operation|, This won't notify
|
||||
// observers that selection was changed. Callers should notify it by
|
||||
// themselves.
|
||||
TabStripSelectionChange SetSelection(
|
||||
ui::ListSelectionModel new_model,
|
||||
TabStripModelObserver::ChangeReason reason,
|
||||
bool triggered_by_other_operation);
|
||||
|
||||
// direction of relative tab movements or selections. kNext indicates moving
|
||||
// forward (positive increment) in the tab strip. kPrevious indicates
|
||||
// backward (negative increment).
|
||||
enum class TabRelativeDirection {
|
||||
kNext,
|
||||
kPrevious,
|
||||
};
|
||||
|
||||
// Selects either the next tab (kNext), or the previous tab (kPrevious).
|
||||
void SelectRelativeTab(TabRelativeDirection direction,
|
||||
TabStripUserGestureDetails detail);
|
||||
|
||||
// Moves the active tabs into the next slot (kNext), or the
|
||||
// previous slot (kPrevious). Respects group boundaries and creates
|
||||
// movement slots into and out of groups.
|
||||
void MoveTabRelative(TabRelativeDirection direction);
|
||||
|
||||
// Does the work of MoveWebContentsAt. This has no checks to make sure the
|
||||
// position is valid, those are done in MoveWebContentsAt.
|
||||
void MoveWebContentsAtImpl(int index,
|
||||
int to_position,
|
||||
bool select_after_move);
|
||||
|
||||
// Implementation of moving a webcontent when the `contents_data` is a tab
|
||||
// collection.
|
||||
void MoveWebContentsAtImplWithCollection(int index,
|
||||
int to_position,
|
||||
bool select_after_move);
|
||||
|
||||
// Implementation of moving a webcontent when the `contents_data` is a vector.
|
||||
void MoveWebContentsAtImplWithVector(int index,
|
||||
int to_position,
|
||||
bool select_after_move);
|
||||
|
||||
// Sends a move notification to the tabstrip model observers for a webcontent.
|
||||
void SendMoveNotificationForWebContents(int index,
|
||||
int to_position,
|
||||
bool select_after_move,
|
||||
content::WebContents* web_contents);
|
||||
|
||||
// Implementation of MoveSelectedTabsTo. Moves |length| of the selected tabs
|
||||
// starting at |start| to |index|. See MoveSelectedTabsTo for more details.
|
||||
void MoveSelectedTabsToImpl(int index, size_t start, size_t length);
|
||||
|
||||
// Adds tabs to newly-allocated group id |new_group|. This group must be new
|
||||
// and have no tabs in it.
|
||||
void AddToNewGroupImpl(std::vector<int> indices,
|
||||
tab_groups::TabGroupId new_group);
|
||||
|
||||
void AddToNewGroupWithCollectionImpl(std::vector<int> indices,
|
||||
const tab_groups::TabGroupId new_group);
|
||||
|
||||
void AddToExistingGroupWithCollectionImpl(std::vector<int> indices,
|
||||
tab_groups::TabGroupId group,
|
||||
const bool add_to_end);
|
||||
|
||||
void AddTabsToGroupCollection(std::vector<tabs::TabModel*> tabs,
|
||||
tabs::TabGroupTabCollection* group_collection,
|
||||
bool start_of_group = false);
|
||||
|
||||
void RemoveTabsFromGroupCollection(
|
||||
std::vector<tabs::TabModel*> tabs,
|
||||
tabs::TabGroupTabCollection* group_collection,
|
||||
bool move_to_left);
|
||||
|
||||
// Adds tabs to existing group |group|. This group must have been initialized
|
||||
// by a previous call to |AddToNewGroupImpl()|.
|
||||
void AddToExistingGroupImpl(const std::vector<int>& indices,
|
||||
const tab_groups::TabGroupId& group,
|
||||
const bool add_to_end = false);
|
||||
|
||||
// Implementation of MoveTabsAndSetGroupImpl. Moves the set of tabs in
|
||||
// |indices| to the |destination_index| and updates the tabs to the
|
||||
// appropriate |group|.
|
||||
void MoveTabsAndSetGroupImpl(const std::vector<int>& indices,
|
||||
int destination_index,
|
||||
std::optional<tab_groups::TabGroupId> group);
|
||||
|
||||
// Moves the tab at |index| to |new_index| and sets its group to |new_group|.
|
||||
// Notifies any observers that group affiliation has changed for the tab.
|
||||
void MoveAndSetGroup(int index,
|
||||
int new_index,
|
||||
std::optional<tab_groups::TabGroupId> new_group);
|
||||
|
||||
void AddToReadLaterImpl(const std::vector<int>& indices);
|
||||
|
||||
// Helper function for MoveAndSetGroup. Removes the tab at |index| from the
|
||||
// group that contains it, if any. Also deletes that group, if it now contains
|
||||
// no tabs. Returns that group.
|
||||
std::optional<tab_groups::TabGroupId> UngroupTab(
|
||||
int index,
|
||||
const std::optional<tab_groups::TabGroupId> old_group);
|
||||
|
||||
// Helper function for MoveAndSetGroup. Adds the tab at |index| to |group|,
|
||||
// updates the group model, and notifies the observers if the group at that
|
||||
// index would change.
|
||||
void GroupTab(int index,
|
||||
const tab_groups::TabGroupId& group,
|
||||
const std::optional<tab_groups::TabGroupId> old_group);
|
||||
|
||||
// Changes the pinned state of the tab at `index`, moving it in the process if
|
||||
// necessary. Returns the new index of the tab.
|
||||
int SetTabPinnedImpl(int index, bool pinned);
|
||||
|
||||
// Updates the pinned state of the tab model and moves the tab within
|
||||
// `contents_data`. This is a helper method called by `SetTabPinnedImpl()`.
|
||||
int UpdatePinAndMoveWebContents(int index, bool pinned);
|
||||
|
||||
// Changes the pinned state of all tabs at `indices`, moving them in the
|
||||
// process if necessary. Returns the new locations of all of those tabs.
|
||||
std::vector<int> SetTabsPinned(const std::vector<int>& indices, bool pinned);
|
||||
|
||||
// Sets the sound content setting for each site at the |indices|.
|
||||
void SetSitesMuted(const std::vector<int>& indices, bool mute) const;
|
||||
|
||||
// Sets the opener of any tabs that reference the tab at |index| to that tab's
|
||||
// opener or null if there's a cycle.
|
||||
void FixOpeners(int index);
|
||||
|
||||
// Makes sure the tab at |index| is not causing a group contiguity error. Will
|
||||
// make the minimum change to ensure that the tab's group is not non-
|
||||
// contiguous as well as ensuring that it is not breaking up a non-contiguous
|
||||
// group, possibly by setting or clearing its group.
|
||||
void EnsureGroupContiguity(int index);
|
||||
|
||||
// Returns a valid index to be selected after the tab at |removing_index| is
|
||||
// closed. If |index| is after |removing_index|, |index| is adjusted to
|
||||
// reflect the fact that |removing_index| is going away.
|
||||
int GetTabIndexAfterClosing(int index, int removing_index) const;
|
||||
|
||||
// Takes the |selection| change and decides whether to forget the openers.
|
||||
void OnActiveTabChanged(const TabStripSelectionChange& selection);
|
||||
|
||||
// Checks if policy allows a tab to be closed.
|
||||
bool PolicyAllowsTabClosing(content::WebContents* contents) const;
|
||||
|
||||
// Determine where to shift selection after a tab is closed.
|
||||
std::optional<int> DetermineNewSelectedIndex(int removed_index) const;
|
||||
|
||||
// The WebContents data currently hosted within this TabStripModel. This must
|
||||
// be kept in sync with |selection_model_|.
|
||||
TabDataVariant contents_data_;
|
||||
|
||||
// The model for tab groups hosted within this TabStripModel.
|
||||
std::unique_ptr<TabGroupModel> group_model_;
|
||||
|
||||
raw_ptr<TabStripModelDelegate, DanglingUntriaged> delegate_;
|
||||
|
||||
bool tab_strip_ui_was_set_ = false;
|
||||
|
||||
base::ObserverList<TabStripModelObserver>::UncheckedAndDanglingUntriaged
|
||||
observers_;
|
||||
|
||||
// A profile associated with this TabStripModel.
|
||||
raw_ptr<Profile, AcrossTasksDanglingUntriaged> profile_;
|
||||
|
||||
// True if all tabs are currently being closed via CloseAllTabs.
|
||||
bool closing_all_ = false;
|
||||
|
||||
// This must be kept in sync with |contents_data_|.
|
||||
ui::ListSelectionModel selection_model_;
|
||||
|
||||
// TabStripModel is not re-entrancy safe. This member is used to guard public
|
||||
// methods that mutate state of |selection_model_| or |contents_data_|.
|
||||
bool reentrancy_guard_ = false;
|
||||
|
||||
TabStripScrubbingMetrics scrubbing_metrics_;
|
||||
|
||||
// Tracks whether a modal UI is showing.
|
||||
bool showing_modal_ui_ = false;
|
||||
|
||||
base::WeakPtrFactory<TabStripModel> weak_factory_{this};
|
||||
};
|
||||
|
||||
// Forbid construction of ScopedObservation and ScopedMultiSourceObservation
|
||||
// with TabStripModel: TabStripModelObserver already implements their
|
||||
// functionality natively.
|
||||
namespace base {
|
||||
|
||||
template <>
|
||||
class ScopedObservation<TabStripModel, TabStripModelObserver> {
|
||||
public:
|
||||
// Deleting the constructor gives a clear error message traceable back to here.
|
||||
explicit ScopedObservation(TabStripModelObserver* observer) = delete;
|
||||
};
|
||||
|
||||
template <>
|
||||
class ScopedMultiSourceObservation<TabStripModel, TabStripModelObserver> {
|
||||
public:
|
||||
// Deleting the constructor gives a clear error message traceable back to
|
||||
// here.
|
||||
explicit ScopedMultiSourceObservation(TabStripModelObserver* observer) =
|
||||
delete;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_H_
|
Loading…
Reference in a new issue