2020-04-23 16:14:31 -03:00
/*
2021-02-16 15:53:47 -03:00
* Copyright ( c ) 2020 - 2021 , Andreas Kling < kling @ serenityos . org >
2021-04-26 06:52:19 -03:00
* Copyright ( c ) 2021 , Maciej Zygmanowski < sppmacd @ pm . me >
2021-09-03 07:14:37 -03:00
* Copyright ( c ) 2021 , Sam Atkins < atkinssj @ serenityos . org >
2022-02-10 16:28:48 -03:00
* Copyright ( c ) 2022 , the SerenityOS developers .
2022-09-12 11:06:24 -03:00
* Copyright ( c ) 2022 , networkException < networkexception @ serenityos . org >
2023-04-17 02:57:16 -03:00
* Copyright ( c ) 2023 , Cameron Youell < cameronyouell @ gmail . com >
2020-04-23 16:14:31 -03:00
*
2021-04-22 05:24:48 -03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-04-23 16:14:31 -03:00
*/
# include "Tab.h"
# include "BookmarksBarWidget.h"
2020-08-10 17:46:23 -03:00
# include "Browser.h"
2021-05-18 14:23:53 -03:00
# include "BrowserWindow.h"
2020-05-23 13:53:09 -03:00
# include "ConsoleWidget.h"
2020-05-05 18:58:22 -03:00
# include "DownloadWidget.h"
2022-12-10 12:50:47 -03:00
# include "History/HistoryWidget.h"
2021-06-07 18:21:16 -03:00
# include "InspectorWidget.h"
2022-03-01 13:10:06 -03:00
# include "StorageWidget.h"
2020-05-07 06:57:53 -03:00
# include <AK/StringBuilder.h>
2021-05-25 09:06:03 -03:00
# include <AK/URL.h>
2020-12-20 07:47:44 -03:00
# include <Applications/Browser/TabGML.h>
2023-06-01 09:21:06 -03:00
# include <Applications/BrowserSettings/Defaults.h>
2022-07-31 18:38:55 -03:00
# include <LibConfig/Client.h>
2020-04-23 16:14:31 -03:00
# include <LibGUI/Action.h>
# include <LibGUI/Application.h>
# include <LibGUI/BoxLayout.h>
# include <LibGUI/Button.h>
2020-05-05 21:33:37 -03:00
# include <LibGUI/Clipboard.h>
2023-09-04 09:12:39 -03:00
# include <LibGUI/ColorPicker.h>
2023-05-17 15:23:34 -03:00
# include <LibGUI/Dialog.h>
# include <LibGUI/InputBox.h>
2020-04-23 16:14:31 -03:00
# include <LibGUI/Menu.h>
2021-07-30 08:16:58 -03:00
# include <LibGUI/MessageBox.h>
2021-04-13 11:18:20 -03:00
# include <LibGUI/Statusbar.h>
2020-04-23 16:14:31 -03:00
# include <LibGUI/TextBox.h>
2021-04-13 11:18:20 -03:00
# include <LibGUI/Toolbar.h>
# include <LibGUI/ToolbarContainer.h>
2020-04-23 16:14:31 -03:00
# include <LibGUI/Window.h>
2023-06-06 22:02:02 -03:00
# include <LibPublicSuffix/URL.h>
2021-11-18 11:01:28 -03:00
# include <LibWeb/HTML/BrowsingContext.h>
2021-05-20 15:47:30 -03:00
# include <LibWeb/HTML/SyntaxHighlighter/SyntaxHighlighter.h>
2021-10-06 15:02:41 -03:00
# include <LibWeb/Layout/BlockContainer.h>
2023-02-25 07:04:29 -03:00
# include <LibWeb/Layout/Viewport.h>
2020-06-01 15:42:50 -03:00
# include <LibWeb/Loader/ResourceLoader.h>
2022-04-30 05:46:33 -03:00
# include <LibWebView/OutOfProcessWebView.h>
2020-04-23 16:14:31 -03:00
namespace Browser {
2022-12-18 19:45:05 -03:00
Tab : : ~ Tab ( )
{
close_sub_widgets ( ) ;
}
2022-12-04 15:02:33 -03:00
URL url_from_user_input ( DeprecatedString const & input )
2020-06-12 16:29:27 -03:00
{
2023-05-23 05:19:59 -03:00
URL url_with_http_schema = URL ( DeprecatedString : : formatted ( " https://{} " , input ) ) ;
2022-02-06 12:29:49 -03:00
if ( url_with_http_schema . is_valid ( ) & & url_with_http_schema . port ( ) . has_value ( ) )
return url_with_http_schema ;
URL url = URL ( input ) ;
2020-06-12 16:29:27 -03:00
if ( url . is_valid ( ) )
return url ;
2022-02-06 12:29:49 -03:00
return url_with_http_schema ;
2020-06-12 16:29:27 -03:00
}
2021-03-27 07:12:35 -03:00
void Tab : : start_download ( const URL & url )
2020-10-02 14:00:45 -03:00
{
2021-05-18 14:23:53 -03:00
auto window = GUI : : Window : : construct ( & this - > window ( ) ) ;
2021-05-31 13:19:13 -03:00
window - > resize ( 300 , 170 ) ;
2022-12-04 15:02:33 -03:00
window - > set_title ( DeprecatedString : : formatted ( " 0% of {} " , url . basename ( ) ) ) ;
2020-10-02 14:00:45 -03:00
window - > set_resizable ( false ) ;
2023-09-18 21:13:48 -03:00
( void ) window - > set_main_widget < DownloadWidget > ( url ) ;
2020-10-02 14:00:45 -03:00
window - > show ( ) ;
}
2022-12-04 15:02:33 -03:00
void Tab : : view_source ( const URL & url , DeprecatedString const & source )
2021-02-23 09:18:22 -03:00
{
2021-05-18 14:23:53 -03:00
auto window = GUI : : Window : : construct ( & this - > window ( ) ) ;
2023-09-18 21:13:48 -03:00
auto editor = window - > set_main_widget < GUI : : TextEditor > ( ) ;
2023-01-06 13:48:37 -03:00
editor - > set_text ( source ) ;
editor - > set_mode ( GUI : : TextEditor : : ReadOnly ) ;
editor - > set_syntax_highlighter ( make < Web : : HTML : : SyntaxHighlighter > ( ) ) ;
editor - > set_ruler_visible ( true ) ;
2023-08-24 19:30:02 -03:00
editor - > set_visualize_trailing_whitespace ( false ) ;
2021-02-23 09:18:22 -03:00
window - > resize ( 640 , 480 ) ;
2022-12-05 22:12:49 -03:00
window - > set_title ( url . to_deprecated_string ( ) ) ;
2022-01-11 00:06:11 -03:00
window - > set_icon ( g_icon_bag . filetype_text ) ;
2022-08-22 16:30:52 -03:00
window - > set_window_mode ( GUI : : WindowMode : : Modeless ) ;
2021-02-23 09:18:22 -03:00
window - > show ( ) ;
}
2023-06-04 05:24:38 -03:00
void Tab : : update_status ( Optional < String > text_override , i32 count_waiting )
2022-02-20 19:03:39 -03:00
{
if ( text_override . has_value ( ) ) {
m_statusbar - > set_text ( * text_override ) ;
return ;
}
if ( m_loaded ) {
2023-06-04 05:24:38 -03:00
m_statusbar - > set_text ( { } ) ;
2022-02-20 19:03:39 -03:00
return ;
}
VERIFY ( m_navigating_url . has_value ( ) ) ;
if ( count_waiting = = 0 ) {
// ex: "Loading google.com"
2023-07-27 06:40:41 -03:00
m_statusbar - > set_text ( String : : formatted ( " Loading {} " , m_navigating_url - > serialized_host ( ) . release_value_but_fixme_should_propagate_errors ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ) ;
2022-02-20 19:03:39 -03:00
} else {
// ex: "google.com is waiting on 5 resources"
2023-07-27 06:40:41 -03:00
m_statusbar - > set_text ( String : : formatted ( " {} is waiting on {} resource{} " , m_navigating_url - > serialized_host ( ) . release_value_but_fixme_should_propagate_errors ( ) , count_waiting , count_waiting = = 1 ? " " sv : " s " sv ) . release_value_but_fixme_should_propagate_errors ( ) ) ;
2022-02-20 19:03:39 -03:00
}
}
2023-08-07 11:44:20 -03:00
Tab : : Tab ( BrowserWindow & window )
2020-04-23 16:14:31 -03:00
{
2023-01-07 09:38:23 -03:00
load_from_gml ( tab_gml ) . release_value_but_fixme_should_propagate_errors ( ) ;
2020-04-23 16:14:31 -03:00
2021-04-13 11:18:20 -03:00
m_toolbar_container = * find_descendant_of_type_named < GUI : : ToolbarContainer > ( " toolbar_container " ) ;
auto & toolbar = * find_descendant_of_type_named < GUI : : Toolbar > ( " toolbar " ) ;
2020-09-14 13:41:22 -03:00
2021-01-01 04:57:48 -03:00
auto & webview_container = * find_descendant_of_type_named < GUI : : Widget > ( " webview_container " ) ;
2020-07-06 16:46:37 -03:00
2023-08-07 11:44:20 -03:00
m_web_content_view = webview_container . add < WebView : : OutOfProcessWebView > ( ) ;
2022-07-31 18:38:55 -03:00
2023-06-01 09:21:06 -03:00
auto preferred_color_scheme = Web : : CSS : : preferred_color_scheme_from_string ( Config : : read_string ( " Browser " sv , " Preferences " sv , " ColorScheme " sv , Browser : : default_color_scheme ) ) ;
2022-07-31 18:38:55 -03:00
m_web_content_view - > set_preferred_color_scheme ( preferred_color_scheme ) ;
2023-04-21 08:54:56 -03:00
content_filters_changed ( ) ;
2023-04-17 14:37:36 -03:00
autoplay_allowlist_changed ( ) ;
2022-04-07 18:16:47 -03:00
m_web_content_view - > set_proxy_mappings ( g_proxies , g_proxy_mappings ) ;
2022-11-08 12:18:11 -03:00
if ( ! g_webdriver_content_ipc_path . is_empty ( ) )
2022-11-04 21:59:10 -03:00
enable_webdriver_mode ( ) ;
2022-10-12 18:51:37 -03:00
2021-05-23 19:58:00 -03:00
auto & go_back_button = toolbar . add_action ( window . go_back_action ( ) ) ;
2022-08-04 19:53:44 -03:00
go_back_button . on_context_menu_request = [ & ] ( auto & ) {
2021-05-23 19:58:00 -03:00
if ( ! m_history . can_go_back ( ) )
return ;
int i = 0 ;
m_go_back_context_menu = GUI : : Menu : : construct ( ) ;
2021-05-26 15:19:35 -03:00
for ( auto & url : m_history . get_back_title_history ( ) ) {
2021-05-23 19:58:00 -03:00
i + + ;
2022-12-05 22:12:49 -03:00
m_go_back_context_menu - > add_action ( GUI : : Action : : create ( url . to_deprecated_string ( ) , g_icon_bag . filetype_html , [ this , i ] ( auto & ) { go_back ( i ) ; } ) ) ;
2021-05-23 19:58:00 -03:00
}
2023-05-21 19:41:18 -03:00
m_go_back_context_menu - > popup ( go_back_button . screen_relative_rect ( ) . bottom_left ( ) . moved_up ( 1 ) ) ;
2021-05-23 19:58:00 -03:00
} ;
auto & go_forward_button = toolbar . add_action ( window . go_forward_action ( ) ) ;
2022-08-04 19:53:44 -03:00
go_forward_button . on_context_menu_request = [ & ] ( auto & ) {
2021-05-23 19:58:00 -03:00
if ( ! m_history . can_go_forward ( ) )
return ;
int i = 0 ;
m_go_forward_context_menu = GUI : : Menu : : construct ( ) ;
2021-05-26 15:19:35 -03:00
for ( auto & url : m_history . get_forward_title_history ( ) ) {
2021-05-23 19:58:00 -03:00
i + + ;
2022-12-05 22:12:49 -03:00
m_go_forward_context_menu - > add_action ( GUI : : Action : : create ( url . to_deprecated_string ( ) , g_icon_bag . filetype_html , [ this , i ] ( auto & ) { go_forward ( i ) ; } ) ) ;
2021-05-23 19:58:00 -03:00
}
2023-05-21 19:41:18 -03:00
m_go_forward_context_menu - > popup ( go_forward_button . screen_relative_rect ( ) . bottom_left ( ) . moved_up ( 1 ) ) ;
2021-05-23 19:58:00 -03:00
} ;
2022-07-10 12:32:05 -03:00
auto & go_home_button = toolbar . add_action ( window . go_home_action ( ) ) ;
go_home_button . set_allowed_mouse_buttons_for_pressing ( GUI : : MouseButton : : Primary | GUI : : MouseButton : : Middle ) ;
go_home_button . on_middle_mouse_click = [ & ] ( auto ) {
on_tab_open_request ( Browser : : url_from_user_input ( g_home_url ) ) ;
} ;
2021-05-18 14:23:53 -03:00
toolbar . add_action ( window . reload_action ( ) ) ;
2020-04-23 16:14:31 -03:00
2021-08-15 02:48:53 -03:00
m_location_box = toolbar . add < GUI : : UrlBox > ( ) ;
2023-06-06 22:02:02 -03:00
m_location_box - > set_placeholder ( " Search or enter address " sv ) ;
2020-04-23 16:14:31 -03:00
m_location_box - > on_return_pressed = [ this ] {
2022-03-19 08:10:38 -03:00
auto url = url_from_location_bar ( ) ;
if ( url . has_value ( ) )
load ( url . release_value ( ) ) ;
} ;
2021-07-30 08:16:58 -03:00
2022-03-19 08:10:38 -03:00
m_location_box - > on_ctrl_return_pressed = [ this ] {
auto url = url_from_location_bar ( MayAppendTLD : : Yes ) ;
if ( url . has_value ( ) )
load ( url . release_value ( ) ) ;
2020-04-23 16:14:31 -03:00
} ;
2021-07-14 12:38:45 -03:00
m_location_box - > add_custom_context_menu_action ( GUI : : Action : : create ( " Paste && Go " , [ this ] ( auto & ) {
2021-11-20 11:22:01 -03:00
auto [ data , mime_type , _ ] = GUI : : Clipboard : : the ( ) . fetch_data_and_type ( ) ;
2022-07-11 14:32:29 -03:00
if ( ! mime_type . starts_with ( " text/ " sv ) )
2021-07-25 06:59:30 -03:00
return ;
2021-11-20 10:44:31 -03:00
auto const & paste_text = data ;
2021-07-25 06:59:30 -03:00
if ( paste_text . is_empty ( ) )
return ;
m_location_box - > set_text ( paste_text ) ;
2020-05-22 16:59:14 -03:00
m_location_box - > on_return_pressed ( ) ;
} ) ) ;
2021-08-15 02:52:27 -03:00
auto bookmark_action = GUI : : Action : : create (
" Bookmark current URL " , { Mod_Ctrl , Key_D } , [ this ] ( auto & ) {
2023-04-17 02:57:16 -03:00
if ( auto result = bookmark_current_url ( ) ; result . is_error ( ) )
GUI : : MessageBox : : show_error ( this - > window ( ) . main_widget ( ) - > window ( ) , MUST ( String : : formatted ( " Failed to bookmark URL: {} " , result . error ( ) ) ) ) ;
2021-08-15 02:52:27 -03:00
} ,
this ) ;
2023-03-28 19:10:00 -03:00
m_reset_zoom_button = toolbar . add < GUI : : Button > ( ) ;
2023-08-01 15:31:54 -03:00
m_reset_zoom_button - > set_tooltip_deprecated ( " Reset zoom level " ) ;
2023-03-28 19:10:00 -03:00
m_reset_zoom_button - > on_click = [ & ] ( auto ) {
view ( ) . reset_zoom ( ) ;
update_reset_zoom_button ( ) ;
2023-08-04 08:37:52 -03:00
window . update_zoom_menu ( ) ;
2023-03-28 19:10:00 -03:00
} ;
m_reset_zoom_button - > set_button_style ( Gfx : : ButtonStyle : : Coolbar ) ;
m_reset_zoom_button - > set_visible ( false ) ;
m_reset_zoom_button - > set_preferred_width ( GUI : : SpecialDimension : : Shrink ) ;
2022-08-04 19:57:00 -03:00
m_bookmark_button = toolbar . add < GUI : : Button > ( ) ;
m_bookmark_button - > set_action ( bookmark_action ) ;
m_bookmark_button - > set_button_style ( Gfx : : ButtonStyle : : Coolbar ) ;
m_bookmark_button - > set_focus_policy ( GUI : : FocusPolicy : : TabFocus ) ;
m_bookmark_button - > set_icon ( g_icon_bag . bookmark_contour ) ;
m_bookmark_button - > set_fixed_size ( 22 , 22 ) ;
2022-11-23 21:18:11 -03:00
view ( ) . on_load_start = [ this ] ( auto & url , bool is_redirect ) {
2022-02-20 19:03:39 -03:00
m_navigating_url = url ;
m_loaded = false ;
2022-11-23 21:18:11 -03:00
// If we are loading due to a redirect, we replace the current history entry
// with the loaded URL
if ( is_redirect ) {
m_history . replace_current ( url , title ( ) ) ;
}
2022-02-20 19:03:39 -03:00
update_status ( ) ;
2020-06-30 16:11:35 -03:00
m_location_box - > set_icon ( nullptr ) ;
2022-12-05 22:12:49 -03:00
m_location_box - > set_text ( url . to_deprecated_string ( ) ) ;
2020-08-19 00:34:28 -03:00
// don't add to history if back or forward is pressed
if ( ! m_is_history_navigation )
2021-05-26 15:19:35 -03:00
m_history . push ( url , title ( ) ) ;
2020-08-19 00:34:28 -03:00
m_is_history_navigation = false ;
2020-04-23 16:14:31 -03:00
update_actions ( ) ;
2022-12-05 22:12:49 -03:00
update_bookmark_button ( url . to_deprecated_string ( ) ) ;
2021-09-01 08:50:47 -03:00
if ( m_dom_inspector_widget )
m_dom_inspector_widget - > clear_dom_json ( ) ;
2021-09-01 13:21:48 -03:00
if ( m_console_widget )
2021-09-04 08:12:12 -03:00
m_console_widget - > reset ( ) ;
2021-09-01 08:50:47 -03:00
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_load_finish = [ this ] ( auto & ) {
2022-02-20 19:03:39 -03:00
m_navigating_url = { } ;
m_loaded = true ;
update_status ( ) ;
2022-12-28 20:26:23 -03:00
if ( m_dom_inspector_widget ) {
2021-09-01 08:50:47 -03:00
m_web_content_view - > inspect_dom_tree ( ) ;
2022-12-28 20:26:23 -03:00
m_web_content_view - > inspect_accessibility_tree ( ) ;
}
2020-04-23 16:14:31 -03:00
} ;
2022-11-11 15:46:22 -03:00
view ( ) . on_navigate_back = [ this ] ( ) {
go_back ( 1 ) ;
} ;
view ( ) . on_navigate_forward = [ this ] ( ) {
go_forward ( 1 ) ;
} ;
view ( ) . on_refresh = [ this ] ( ) {
reload ( ) ;
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_link_click = [ this ] ( auto & url , auto & target , unsigned modifiers ) {
2020-05-22 22:35:09 -03:00
if ( target = = " _blank " | | modifiers = = Mod_Ctrl ) {
on_tab_open_request ( url ) ;
} else {
2020-07-06 16:46:37 -03:00
load ( url ) ;
2020-04-23 16:14:31 -03:00
}
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_resource_status_change = [ this ] ( auto count_waiting ) {
2022-02-20 19:03:39 -03:00
update_status ( { } , count_waiting ) ;
} ;
2022-11-09 11:51:39 -03:00
view ( ) . on_restore_window = [ this ] ( ) {
this - > window ( ) . show ( ) ;
this - > window ( ) . move_to_front ( ) ;
m_web_content_view - > set_system_visibility_state ( true ) ;
} ;
2022-12-06 17:27:44 -03:00
view ( ) . on_reposition_window = [ this ] ( Gfx : : IntPoint position ) {
2022-11-09 11:51:39 -03:00
this - > window ( ) . move_to ( position ) ;
return this - > window ( ) . position ( ) ;
} ;
2022-12-06 18:35:32 -03:00
view ( ) . on_resize_window = [ this ] ( Gfx : : IntSize size ) {
2022-11-09 11:51:39 -03:00
this - > window ( ) . resize ( size ) ;
return this - > window ( ) . size ( ) ;
} ;
2022-11-09 12:04:09 -03:00
view ( ) . on_maximize_window = [ this ] ( ) {
this - > window ( ) . set_maximized ( true ) ;
return this - > window ( ) . rect ( ) ;
} ;
view ( ) . on_minimize_window = [ this ] ( ) {
this - > window ( ) . set_minimized ( true ) ;
m_web_content_view - > set_system_visibility_state ( false ) ;
return this - > window ( ) . rect ( ) ;
} ;
2022-11-09 15:09:17 -03:00
view ( ) . on_fullscreen_window = [ this ] ( ) {
this - > window ( ) . set_fullscreen ( true ) ;
return this - > window ( ) . rect ( ) ;
} ;
2020-05-05 17:42:50 -03:00
m_link_context_menu = GUI : : Menu : : construct ( ) ;
2022-09-08 00:18:19 -03:00
auto link_default_action = GUI : : Action : : create ( " &Open " , g_icon_bag . go_to , [ this ] ( auto & ) {
2022-04-06 10:15:07 -03:00
view ( ) . on_link_click ( m_link_context_menu_url , " " , 0 ) ;
2020-08-29 05:56:42 -03:00
} ) ;
2020-10-02 14:00:45 -03:00
m_link_context_menu - > add_action ( link_default_action ) ;
m_link_context_menu_default_action = link_default_action ;
2022-09-08 00:18:19 -03:00
m_link_context_menu - > add_action ( GUI : : Action : : create ( " Open in New &Tab " , g_icon_bag . new_tab , [ this ] ( auto & ) {
2022-04-06 10:15:07 -03:00
view ( ) . on_link_click ( m_link_context_menu_url , " _blank " , 0 ) ;
2020-05-05 17:42:50 -03:00
} ) ) ;
2020-10-02 14:00:45 -03:00
m_link_context_menu - > add_separator ( ) ;
2022-09-08 00:18:19 -03:00
m_link_context_menu - > add_action ( GUI : : Action : : create ( " &Copy URL " , g_icon_bag . copy , [ this ] ( auto & ) {
2022-12-05 22:12:49 -03:00
GUI : : Clipboard : : the ( ) . set_plain_text ( m_link_context_menu_url . to_deprecated_string ( ) ) ;
2020-05-05 21:33:37 -03:00
} ) ) ;
2020-05-05 18:58:22 -03:00
m_link_context_menu - > add_separator ( ) ;
2022-09-08 00:18:19 -03:00
m_link_context_menu - > add_action ( GUI : : Action : : create ( " &Download " , g_icon_bag . download , [ this ] ( auto & ) {
2020-10-02 14:00:45 -03:00
start_download ( m_link_context_menu_url ) ;
2020-05-05 18:58:22 -03:00
} ) ) ;
2021-08-17 13:00:27 -03:00
m_link_context_menu - > add_separator ( ) ;
m_link_context_menu - > add_action ( window . inspect_dom_node_action ( ) ) ;
2020-05-05 17:42:50 -03:00
2023-05-17 13:37:31 -03:00
view ( ) . on_link_context_menu_request = [ this ] ( auto & url , auto widget_position ) {
2020-07-06 15:00:56 -03:00
m_link_context_menu_url = url ;
2023-05-17 13:37:31 -03:00
auto screen_position = view ( ) . screen_relative_rect ( ) . location ( ) . translated ( widget_position ) ;
2020-08-29 05:56:42 -03:00
m_link_context_menu - > popup ( screen_position , m_link_context_menu_default_action ) ;
2020-05-05 17:42:50 -03:00
} ;
2020-10-02 14:03:10 -03:00
m_image_context_menu = GUI : : Menu : : construct ( ) ;
2022-09-08 00:18:19 -03:00
m_image_context_menu - > add_action ( GUI : : Action : : create ( " &Open Image " , g_icon_bag . filetype_image , [ this ] ( auto & ) {
2022-04-06 10:15:07 -03:00
view ( ) . on_link_click ( m_image_context_menu_url , " " , 0 ) ;
2020-10-02 14:03:10 -03:00
} ) ) ;
2022-09-08 00:18:19 -03:00
m_image_context_menu - > add_action ( GUI : : Action : : create ( " Open Image in New &Tab " , g_icon_bag . new_tab , [ this ] ( auto & ) {
2022-04-06 10:15:07 -03:00
view ( ) . on_link_click ( m_image_context_menu_url , " _blank " , 0 ) ;
2020-10-02 14:03:10 -03:00
} ) ) ;
m_image_context_menu - > add_separator ( ) ;
2022-09-08 00:18:19 -03:00
m_image_context_menu - > add_action ( GUI : : Action : : create ( " &Copy Image " , g_icon_bag . copy , [ this ] ( auto & ) {
2020-10-02 14:03:10 -03:00
if ( m_image_context_menu_bitmap . is_valid ( ) )
GUI : : Clipboard : : the ( ) . set_bitmap ( * m_image_context_menu_bitmap . bitmap ( ) ) ;
} ) ) ;
2022-09-08 00:18:19 -03:00
m_image_context_menu - > add_action ( GUI : : Action : : create ( " Copy Image &URL " , g_icon_bag . copy , [ this ] ( auto & ) {
2022-12-05 22:12:49 -03:00
GUI : : Clipboard : : the ( ) . set_plain_text ( m_image_context_menu_url . to_deprecated_string ( ) ) ;
2020-10-02 14:03:10 -03:00
} ) ) ;
m_image_context_menu - > add_separator ( ) ;
2022-09-08 00:18:19 -03:00
m_image_context_menu - > add_action ( GUI : : Action : : create ( " &Download " , g_icon_bag . download , [ this ] ( auto & ) {
2020-10-02 14:03:10 -03:00
start_download ( m_image_context_menu_url ) ;
} ) ) ;
2021-08-17 13:00:27 -03:00
m_image_context_menu - > add_separator ( ) ;
m_image_context_menu - > add_action ( window . inspect_dom_node_action ( ) ) ;
2020-10-02 14:03:10 -03:00
2023-05-17 13:37:31 -03:00
view ( ) . on_image_context_menu_request = [ this ] ( auto & image_url , auto widget_position , Gfx : : ShareableBitmap const & shareable_bitmap ) {
2020-10-02 14:03:10 -03:00
m_image_context_menu_url = image_url ;
m_image_context_menu_bitmap = shareable_bitmap ;
2023-05-17 13:37:31 -03:00
auto screen_position = view ( ) . screen_relative_rect ( ) . location ( ) . translated ( widget_position ) ;
2020-10-02 14:03:10 -03:00
m_image_context_menu - > popup ( screen_position ) ;
2023-05-15 11:00:07 -03:00
} ;
2023-06-16 11:51:38 -03:00
m_media_context_menu_play_pause_action = GUI : : Action : : create ( " &Play " , g_icon_bag . play , [ this ] ( auto & ) {
view ( ) . toggle_media_play_state ( ) ;
2023-05-15 11:00:07 -03:00
} ) ;
2023-06-16 12:29:54 -03:00
m_media_context_menu_mute_unmute_action = GUI : : Action : : create ( " &Mute " , g_icon_bag . mute , [ this ] ( auto & ) {
view ( ) . toggle_media_mute_state ( ) ;
} ) ;
2023-06-16 11:51:38 -03:00
m_media_context_menu_controls_action = GUI : : Action : : create_checkable ( " Show &Controls " , [ this ] ( auto & ) {
view ( ) . toggle_media_controls_state ( ) ;
2023-05-15 11:00:07 -03:00
} ) ;
2023-06-16 11:51:38 -03:00
m_media_context_menu_loop_action = GUI : : Action : : create_checkable ( " &Loop " , [ this ] ( auto & ) {
view ( ) . toggle_media_loop_state ( ) ;
2023-05-15 11:00:07 -03:00
} ) ;
2023-06-16 12:05:15 -03:00
m_audio_context_menu = GUI : : Menu : : construct ( ) ;
m_audio_context_menu - > add_action ( * m_media_context_menu_play_pause_action ) ;
2023-06-16 12:29:54 -03:00
m_audio_context_menu - > add_action ( * m_media_context_menu_mute_unmute_action ) ;
2023-06-16 12:05:15 -03:00
m_audio_context_menu - > add_action ( * m_media_context_menu_controls_action ) ;
m_audio_context_menu - > add_action ( * m_media_context_menu_loop_action ) ;
m_audio_context_menu - > add_separator ( ) ;
2023-06-19 08:15:13 -03:00
m_audio_context_menu - > add_action ( GUI : : Action : : create ( " &Open Audio " , g_icon_bag . filetype_audio , [ this ] ( auto & ) {
view ( ) . on_link_click ( m_media_context_menu_url , " " , 0 ) ;
} ) ) ;
m_audio_context_menu - > add_action ( GUI : : Action : : create ( " Open Audio in New &Tab " , g_icon_bag . new_tab , [ this ] ( auto & ) {
view ( ) . on_link_click ( m_media_context_menu_url , " _blank " , 0 ) ;
} ) ) ;
m_audio_context_menu - > add_separator ( ) ;
2023-06-16 12:05:15 -03:00
m_audio_context_menu - > add_action ( GUI : : Action : : create ( " Copy Audio &URL " , g_icon_bag . copy , [ this ] ( auto & ) {
GUI : : Clipboard : : the ( ) . set_plain_text ( m_media_context_menu_url . to_deprecated_string ( ) ) ;
} ) ) ;
m_audio_context_menu - > add_separator ( ) ;
m_audio_context_menu - > add_action ( GUI : : Action : : create ( " &Download " , g_icon_bag . download , [ this ] ( auto & ) {
start_download ( m_media_context_menu_url ) ;
} ) ) ;
m_audio_context_menu - > add_separator ( ) ;
m_audio_context_menu - > add_action ( window . inspect_dom_node_action ( ) ) ;
2023-05-15 11:00:07 -03:00
m_video_context_menu = GUI : : Menu : : construct ( ) ;
2023-06-16 11:51:38 -03:00
m_video_context_menu - > add_action ( * m_media_context_menu_play_pause_action ) ;
2023-06-16 12:29:54 -03:00
m_video_context_menu - > add_action ( * m_media_context_menu_mute_unmute_action ) ;
2023-06-16 11:51:38 -03:00
m_video_context_menu - > add_action ( * m_media_context_menu_controls_action ) ;
m_video_context_menu - > add_action ( * m_media_context_menu_loop_action ) ;
2023-05-15 11:00:07 -03:00
m_video_context_menu - > add_separator ( ) ;
m_video_context_menu - > add_action ( GUI : : Action : : create ( " &Open Video " , g_icon_bag . filetype_video , [ this ] ( auto & ) {
2023-06-16 11:51:38 -03:00
view ( ) . on_link_click ( m_media_context_menu_url , " " , 0 ) ;
2023-05-15 11:00:07 -03:00
} ) ) ;
m_video_context_menu - > add_action ( GUI : : Action : : create ( " Open Video in New &Tab " , g_icon_bag . new_tab , [ this ] ( auto & ) {
2023-06-16 11:51:38 -03:00
view ( ) . on_link_click ( m_media_context_menu_url , " _blank " , 0 ) ;
2023-05-15 11:00:07 -03:00
} ) ) ;
m_video_context_menu - > add_separator ( ) ;
m_video_context_menu - > add_action ( GUI : : Action : : create ( " Copy Video &URL " , g_icon_bag . copy , [ this ] ( auto & ) {
2023-06-16 11:51:38 -03:00
GUI : : Clipboard : : the ( ) . set_plain_text ( m_media_context_menu_url . to_deprecated_string ( ) ) ;
2023-05-15 11:00:07 -03:00
} ) ) ;
m_video_context_menu - > add_separator ( ) ;
m_video_context_menu - > add_action ( GUI : : Action : : create ( " &Download " , g_icon_bag . download , [ this ] ( auto & ) {
2023-06-16 11:51:38 -03:00
start_download ( m_media_context_menu_url ) ;
2023-05-15 11:00:07 -03:00
} ) ) ;
m_video_context_menu - > add_separator ( ) ;
m_video_context_menu - > add_action ( window . inspect_dom_node_action ( ) ) ;
2023-06-16 11:51:38 -03:00
view ( ) . on_media_context_menu_request = [ this ] ( auto widget_position , Web : : Page : : MediaContextMenu const & menu ) {
m_media_context_menu_url = menu . media_url ;
2023-05-15 11:00:07 -03:00
2023-06-16 11:51:38 -03:00
if ( menu . is_playing ) {
m_media_context_menu_play_pause_action - > set_icon ( g_icon_bag . pause ) ;
m_media_context_menu_play_pause_action - > set_text ( " &Pause " sv ) ;
2023-05-15 11:00:07 -03:00
} else {
2023-06-16 11:51:38 -03:00
m_media_context_menu_play_pause_action - > set_icon ( g_icon_bag . play ) ;
m_media_context_menu_play_pause_action - > set_text ( " &Play " sv ) ;
2023-05-15 11:00:07 -03:00
}
2023-06-16 12:29:54 -03:00
if ( menu . is_muted ) {
m_media_context_menu_mute_unmute_action - > set_icon ( g_icon_bag . unmute ) ;
m_media_context_menu_mute_unmute_action - > set_text ( " Un&mute " sv ) ;
} else {
m_media_context_menu_mute_unmute_action - > set_icon ( g_icon_bag . mute ) ;
m_media_context_menu_mute_unmute_action - > set_text ( " &Mute " sv ) ;
}
2023-06-16 11:51:38 -03:00
m_media_context_menu_controls_action - > set_checked ( menu . has_user_agent_controls ) ;
m_media_context_menu_loop_action - > set_checked ( menu . is_looping ) ;
2023-05-15 11:00:07 -03:00
2023-05-17 13:37:31 -03:00
auto screen_position = view ( ) . screen_relative_rect ( ) . location ( ) . translated ( widget_position ) ;
2023-06-16 11:51:38 -03:00
if ( menu . is_video )
m_video_context_menu - > popup ( screen_position ) ;
2023-06-16 12:05:15 -03:00
else
m_audio_context_menu - > popup ( screen_position ) ;
2020-10-02 14:03:10 -03:00
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_link_middle_click = [ this ] ( auto & href , auto & , auto ) {
view ( ) . on_link_click ( href , " _blank " , 0 ) ;
2020-05-06 16:34:10 -03:00
} ;
2023-06-07 17:37:30 -03:00
view ( ) . on_title_change = [ this ] ( auto const & title ) {
m_history . update_title ( title ) ;
m_title = title ;
2020-04-23 16:14:31 -03:00
if ( on_title_change )
on_title_change ( m_title ) ;
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_favicon_change = [ this ] ( auto & icon ) {
2020-04-24 17:47:53 -03:00
m_icon = icon ;
2020-06-29 15:35:53 -03:00
m_location_box - > set_icon ( & icon ) ;
2020-04-24 17:28:05 -03:00
if ( on_favicon_change )
2020-04-24 17:47:53 -03:00
on_favicon_change ( icon ) ;
2020-04-24 17:28:05 -03:00
} ;
2022-11-11 11:24:07 -03:00
view ( ) . on_get_all_cookies = [ this ] ( auto & url ) - > Vector < Web : : Cookie : : Cookie > {
if ( on_get_all_cookies )
return on_get_all_cookies ( url ) ;
return { } ;
} ;
2022-11-11 11:55:11 -03:00
view ( ) . on_get_named_cookie = [ this ] ( auto & url , auto & name ) - > Optional < Web : : Cookie : : Cookie > {
if ( on_get_named_cookie )
return on_get_named_cookie ( url , name ) ;
return { } ;
} ;
2022-12-04 15:02:33 -03:00
view ( ) . on_get_cookie = [ this ] ( auto & url , auto source ) - > DeprecatedString {
2021-04-11 11:53:15 -03:00
if ( on_get_cookie )
2021-04-13 18:30:41 -03:00
return on_get_cookie ( url , source ) ;
2021-04-11 11:53:15 -03:00
return { } ;
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_set_cookie = [ this ] ( auto & url , auto & cookie , auto source ) {
2021-04-11 11:53:15 -03:00
if ( on_set_cookie )
2021-04-13 18:30:41 -03:00
on_set_cookie ( url , cookie , source ) ;
2021-04-11 11:53:15 -03:00
} ;
2022-11-28 13:24:04 -03:00
view ( ) . on_update_cookie = [ this ] ( auto & cookie ) {
2022-11-11 13:21:00 -03:00
if ( on_update_cookie )
2022-11-28 13:24:04 -03:00
on_update_cookie ( cookie ) ;
2022-11-11 13:21:00 -03:00
} ;
2023-05-17 15:23:34 -03:00
view ( ) . on_request_alert = [ this ] ( String const & message ) {
auto & window = this - > window ( ) ;
m_dialog = GUI : : MessageBox : : create ( & window , message , " Alert " sv , GUI : : MessageBox : : Type : : Information , GUI : : MessageBox : : InputType : : OK ) . release_value_but_fixme_should_propagate_errors ( ) ;
m_dialog - > set_icon ( window . icon ( ) ) ;
m_dialog - > exec ( ) ;
view ( ) . alert_closed ( ) ;
m_dialog = nullptr ;
} ;
view ( ) . on_request_confirm = [ this ] ( String const & message ) {
auto & window = this - > window ( ) ;
m_dialog = GUI : : MessageBox : : create ( & window , message , " Confirm " sv , GUI : : MessageBox : : Type : : Warning , GUI : : MessageBox : : InputType : : OKCancel ) . release_value_but_fixme_should_propagate_errors ( ) ;
m_dialog - > set_icon ( window . icon ( ) ) ;
view ( ) . confirm_closed ( m_dialog - > exec ( ) = = GUI : : Dialog : : ExecResult : : OK ) ;
m_dialog = nullptr ;
} ;
view ( ) . on_request_prompt = [ this ] ( String const & message , String const & default_ ) {
auto & window = this - > window ( ) ;
String mutable_value = default_ ;
m_dialog = GUI : : InputBox : : create ( & window , mutable_value , message , " Prompt " sv , GUI : : InputType : : Text ) . release_value_but_fixme_should_propagate_errors ( ) ;
m_dialog - > set_icon ( window . icon ( ) ) ;
if ( m_dialog - > exec ( ) = = GUI : : InputBox : : ExecResult : : OK ) {
auto const & dialog = static_cast < GUI : : InputBox const & > ( * m_dialog ) ;
auto response = dialog . text_value ( ) ;
view ( ) . prompt_closed ( move ( response ) ) ;
} else {
view ( ) . prompt_closed ( { } ) ;
}
m_dialog = nullptr ;
} ;
view ( ) . on_request_set_prompt_text = [ this ] ( String const & message ) {
if ( m_dialog & & is < GUI : : InputBox > ( * m_dialog ) )
static_cast < GUI : : InputBox & > ( * m_dialog ) . set_text_value ( message ) ;
} ;
view ( ) . on_request_accept_dialog = [ this ] ( ) {
if ( m_dialog )
m_dialog - > done ( GUI : : Dialog : : ExecResult : : OK ) ;
} ;
view ( ) . on_request_dismiss_dialog = [ this ] ( ) {
if ( m_dialog )
m_dialog - > done ( GUI : : Dialog : : ExecResult : : Cancel ) ;
} ;
2023-09-04 09:12:39 -03:00
view ( ) . on_request_color_picker = [ this ] ( Color current_color ) {
auto & window = this - > window ( ) ;
m_dialog = GUI : : ColorPicker : : construct ( current_color , & window ) ;
auto & dialog = static_cast < GUI : : ColorPicker & > ( * m_dialog ) ;
dialog . set_icon ( window . icon ( ) ) ;
dialog . set_color_has_alpha_channel ( false ) ;
if ( dialog . exec ( ) = = GUI : : ColorPicker : : ExecResult : : OK )
view ( ) . color_picker_closed ( dialog . color ( ) ) ;
else
view ( ) . color_picker_closed ( { } ) ;
m_dialog = nullptr ;
} ;
2023-08-23 12:25:24 -03:00
view ( ) . on_received_source = [ this ] ( auto & url , auto & source ) {
2021-03-27 07:12:35 -03:00
view_source ( url , source ) ;
2021-02-23 09:18:22 -03:00
} ;
2023-08-23 12:25:24 -03:00
view ( ) . on_received_dom_tree = [ this ] ( auto & dom_tree ) {
2021-08-23 12:16:08 -03:00
if ( m_dom_inspector_widget )
m_dom_inspector_widget - > set_dom_json ( dom_tree ) ;
2021-06-07 18:21:16 -03:00
} ;
2023-08-23 12:25:24 -03:00
view ( ) . on_received_dom_node_properties = [ this ] ( auto node_id , auto & specified , auto & computed , auto & custom_properties , auto & node_box_sizing , auto & aria_properties_state ) {
2023-05-21 10:52:03 -03:00
m_dom_inspector_widget - > set_dom_node_properties_json ( { node_id } , specified , computed , custom_properties , node_box_sizing , aria_properties_state ) ;
2021-08-27 08:47:30 -03:00
} ;
2023-08-23 12:25:24 -03:00
view ( ) . on_received_accessibility_tree = [ this ] ( auto & accessibility_tree ) {
2022-12-28 20:26:23 -03:00
if ( m_dom_inspector_widget )
m_dom_inspector_widget - > set_accessibility_json ( accessibility_tree ) ;
} ;
2020-05-05 18:58:22 -03:00
auto focus_location_box_action = GUI : : Action : : create (
2021-06-24 12:41:16 -03:00
" Focus location box " , { Mod_Ctrl , Key_L } , Key_F6 , [ this ] ( auto & ) {
2020-05-05 18:58:22 -03:00
m_location_box - > set_focus ( true ) ;
2021-08-15 02:48:53 -03:00
m_location_box - > select_current_line ( ) ;
2020-05-05 18:58:22 -03:00
} ,
this ) ;
2020-04-23 16:14:31 -03:00
2021-04-13 11:18:20 -03:00
m_statusbar = * find_descendant_of_type_named < GUI : : Statusbar > ( " statusbar " ) ;
2020-04-23 16:14:31 -03:00
2022-04-06 10:15:07 -03:00
view ( ) . on_link_hover = [ this ] ( auto & url ) {
2023-06-04 05:24:38 -03:00
update_status ( String : : from_deprecated_string ( url . to_deprecated_string ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ) ;
2020-04-23 16:14:31 -03:00
} ;
2023-05-17 13:37:31 -03:00
view ( ) . on_link_unhover = [ this ] ( ) {
view ( ) . set_override_cursor ( Gfx : : StandardCursor : : None ) ;
update_status ( ) ;
2020-05-10 16:04:37 -03:00
} ;
2023-03-20 19:39:20 -03:00
view ( ) . on_new_tab = [ this ] ( auto activate_tab ) {
auto & tab = this - > window ( ) . create_new_tab ( URL ( " about:blank " ) , activate_tab ) ;
2023-03-15 09:48:16 -03:00
return tab . view ( ) . handle ( ) ;
} ;
2023-03-20 20:52:00 -03:00
view ( ) . on_activate_tab = [ this ] ( ) {
on_activate_tab_request ( * this ) ;
} ;
2023-03-07 00:00:17 -03:00
view ( ) . on_close = [ this ] {
on_tab_close_request ( * this ) ;
} ;
2020-05-18 19:37:12 -03:00
m_tab_context_menu = GUI : : Menu : : construct ( ) ;
2021-08-03 12:02:10 -03:00
m_tab_context_menu - > add_action ( GUI : : CommonActions : : make_reload_action ( [ this ] ( auto & ) {
2022-08-04 20:05:46 -03:00
reload ( ) ;
2020-05-18 19:37:12 -03:00
} ) ) ;
2021-08-03 12:02:10 -03:00
m_tab_context_menu - > add_action ( GUI : : CommonActions : : make_close_tab_action ( [ this ] ( auto & ) {
2020-05-18 19:37:12 -03:00
on_tab_close_request ( * this ) ;
} ) ) ;
2022-01-11 00:06:11 -03:00
m_tab_context_menu - > add_action ( GUI : : Action : : create ( " &Duplicate Tab " , g_icon_bag . duplicate_tab , [ this ] ( auto & ) {
2021-08-06 13:21:14 -03:00
on_tab_open_request ( url ( ) ) ;
} ) ) ;
2022-09-08 00:18:19 -03:00
m_tab_context_menu - > add_action ( GUI : : Action : : create ( " Close &Other Tabs " , g_icon_bag . close_other_tabs , [ this ] ( auto & ) {
2021-08-06 13:21:14 -03:00
on_tab_close_other_request ( * this ) ;
} ) ) ;
2020-06-27 17:23:21 -03:00
2023-05-17 10:53:13 -03:00
auto take_visible_screenshot_action = GUI : : Action : : create (
" Take &Visible Screenshot " sv , g_icon_bag . filetype_image , [ this ] ( auto & ) {
if ( auto result = view ( ) . take_screenshot ( WebView : : ViewImplementation : : ScreenshotType : : Visible ) ; result . is_error ( ) ) {
auto error = String : : formatted ( " {} " , result . error ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ;
GUI : : MessageBox : : show_error ( & this - > window ( ) , error ) ;
}
} ,
this ) ;
2023-08-07 06:12:38 -03:00
take_visible_screenshot_action - > set_status_tip ( " Save a screenshot of the visible portion of the current tab to the Downloads directory " _string ) ;
2023-05-17 10:53:13 -03:00
auto take_full_screenshot_action = GUI : : Action : : create (
" Take &Full Screenshot " sv , g_icon_bag . filetype_image , [ this ] ( auto & ) {
if ( auto result = view ( ) . take_screenshot ( WebView : : ViewImplementation : : ScreenshotType : : Full ) ; result . is_error ( ) ) {
auto error = String : : formatted ( " {} " , result . error ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ;
GUI : : MessageBox : : show_error ( & this - > window ( ) , error ) ;
}
} ,
this ) ;
2023-08-07 06:12:38 -03:00
take_full_screenshot_action - > set_status_tip ( " Save a screenshot of the entirety of the current tab to the Downloads directory " _string ) ;
2023-05-17 10:53:13 -03:00
2020-06-27 17:23:21 -03:00
m_page_context_menu = GUI : : Menu : : construct ( ) ;
2021-05-18 14:23:53 -03:00
m_page_context_menu - > add_action ( window . go_back_action ( ) ) ;
m_page_context_menu - > add_action ( window . go_forward_action ( ) ) ;
m_page_context_menu - > add_action ( window . reload_action ( ) ) ;
2020-06-27 17:23:21 -03:00
m_page_context_menu - > add_separator ( ) ;
2021-07-14 09:33:35 -03:00
m_page_context_menu - > add_action ( window . copy_selection_action ( ) ) ;
2021-07-14 09:55:36 -03:00
m_page_context_menu - > add_action ( window . select_all_action ( ) ) ;
2021-07-14 09:33:35 -03:00
m_page_context_menu - > add_separator ( ) ;
2023-05-17 10:53:13 -03:00
m_page_context_menu - > add_action ( move ( take_visible_screenshot_action ) ) ;
m_page_context_menu - > add_action ( move ( take_full_screenshot_action ) ) ;
2023-05-16 08:53:53 -03:00
m_page_context_menu - > add_separator ( ) ;
2021-05-18 14:23:53 -03:00
m_page_context_menu - > add_action ( window . view_source_action ( ) ) ;
m_page_context_menu - > add_action ( window . inspect_dom_tree_action ( ) ) ;
2021-08-17 13:00:27 -03:00
m_page_context_menu - > add_action ( window . inspect_dom_node_action ( ) ) ;
2023-05-17 13:37:31 -03:00
view ( ) . on_context_menu_request = [ & ] ( auto widget_position ) {
auto screen_position = view ( ) . screen_relative_rect ( ) . location ( ) . translated ( widget_position ) ;
2020-06-27 17:23:21 -03:00
m_page_context_menu - > popup ( screen_position ) ;
} ;
2020-04-23 16:14:31 -03:00
}
2023-03-28 19:10:00 -03:00
void Tab : : update_reset_zoom_button ( )
{
auto zoom_level = view ( ) . zoom_level ( ) ;
if ( zoom_level ! = 1.0f ) {
m_reset_zoom_button - > set_text ( MUST ( String : : formatted ( " {}% " , round_to < int > ( zoom_level * 100 ) ) ) ) ;
m_reset_zoom_button - > set_visible ( true ) ;
} else {
m_reset_zoom_button - > set_visible ( false ) ;
}
}
2022-03-19 08:10:38 -03:00
Optional < URL > Tab : : url_from_location_bar ( MayAppendTLD may_append_tld )
{
2022-12-04 15:02:33 -03:00
DeprecatedString text = m_location_box - > text ( ) ;
2022-03-19 08:10:38 -03:00
StringBuilder builder ;
builder . append ( text ) ;
if ( may_append_tld = = MayAppendTLD : : Yes ) {
// FIXME: Expand the list of top level domains.
2022-07-11 14:32:29 -03:00
if ( ! ( text . ends_with ( " .com " sv ) | | text . ends_with ( " .net " sv ) | | text . ends_with ( " .org " sv ) ) ) {
builder . append ( " .com " sv ) ;
2022-03-19 08:10:38 -03:00
}
}
2023-01-26 15:58:09 -03:00
auto final_text = builder . to_deprecated_string ( ) ;
2022-03-19 08:10:38 -03:00
2023-06-06 22:02:02 -03:00
auto error_or_absolute_url = PublicSuffix : : absolute_url ( final_text ) ;
if ( error_or_absolute_url . is_error ( ) ) {
if ( g_search_engine . is_empty ( ) ) {
GUI : : MessageBox : : show ( & this - > window ( ) , " Select a search engine in the Settings menu before searching. " sv , " No search engine selected " sv , GUI : : MessageBox : : Type : : Information ) ;
return { } ;
}
return URL ( g_search_engine . replace ( " {} " sv , URL : : percent_encode ( final_text ) , ReplaceMode : : FirstOnly ) ) ;
}
return URL ( error_or_absolute_url . release_value ( ) ) ;
2022-03-19 08:10:38 -03:00
}
2020-07-07 10:04:05 -03:00
void Tab : : load ( const URL & url , LoadType load_type )
2020-04-23 16:14:31 -03:00
{
2020-08-19 00:34:28 -03:00
m_is_history_navigation = ( load_type = = LoadType : : HistoryNavigation ) ;
2021-08-24 11:35:46 -03:00
m_web_content_view - > load ( url ) ;
2021-08-15 02:48:53 -03:00
m_location_box - > set_focus ( false ) ;
2020-07-06 16:46:37 -03:00
}
URL Tab : : url ( ) const
{
return m_web_content_view - > url ( ) ;
}
void Tab : : reload ( )
{
2023-08-28 16:54:36 -03:00
if ( m_history . is_empty ( ) )
return ;
2020-07-06 16:46:37 -03:00
load ( url ( ) ) ;
2020-04-23 16:14:31 -03:00
}
2021-05-23 19:58:00 -03:00
void Tab : : go_back ( int steps )
2020-07-07 10:04:05 -03:00
{
2023-08-18 19:33:25 -03:00
if ( ! m_history . can_go_back ( steps ) )
return ;
2021-05-23 19:58:00 -03:00
m_history . go_back ( steps ) ;
2020-07-07 10:04:05 -03:00
update_actions ( ) ;
2021-05-26 15:19:35 -03:00
load ( m_history . current ( ) . url , LoadType : : HistoryNavigation ) ;
2020-07-07 10:04:05 -03:00
}
2021-05-23 19:58:00 -03:00
void Tab : : go_forward ( int steps )
2020-07-07 10:04:05 -03:00
{
2023-08-18 19:33:25 -03:00
if ( ! m_history . can_go_forward ( steps ) )
return ;
2021-05-23 19:58:00 -03:00
m_history . go_forward ( steps ) ;
2020-07-07 10:04:05 -03:00
update_actions ( ) ;
2021-05-26 15:19:35 -03:00
load ( m_history . current ( ) . url , LoadType : : HistoryNavigation ) ;
2020-07-07 10:04:05 -03:00
}
2020-04-23 16:14:31 -03:00
void Tab : : update_actions ( )
{
2021-05-18 14:23:53 -03:00
auto & window = this - > window ( ) ;
if ( this ! = & window . active_tab ( ) )
return ;
window . go_back_action ( ) . set_enabled ( m_history . can_go_back ( ) ) ;
window . go_forward_action ( ) . set_enabled ( m_history . can_go_forward ( ) ) ;
2023-08-28 16:54:36 -03:00
window . reload_action ( ) . set_enabled ( ! m_history . is_empty ( ) ) ;
2020-04-23 16:14:31 -03:00
}
2023-04-17 02:57:16 -03:00
ErrorOr < void > Tab : : bookmark_current_url ( )
2021-08-15 02:52:27 -03:00
{
2022-12-05 22:12:49 -03:00
auto url = this - > url ( ) . to_deprecated_string ( ) ;
2021-08-15 02:52:27 -03:00
if ( BookmarksBarWidget : : the ( ) . contains_bookmark ( url ) ) {
2023-04-17 02:57:16 -03:00
TRY ( BookmarksBarWidget : : the ( ) . remove_bookmark ( url ) ) ;
2021-08-15 02:52:27 -03:00
} else {
2023-04-17 02:57:16 -03:00
TRY ( BookmarksBarWidget : : the ( ) . add_bookmark ( url , m_title ) ) ;
2021-08-15 02:52:27 -03:00
}
2023-04-17 02:57:16 -03:00
return { } ;
2021-08-15 02:52:27 -03:00
}
2023-04-17 02:57:16 -03:00
void Tab : : update_bookmark_button ( StringView url )
2020-04-23 16:14:31 -03:00
{
2020-04-25 12:20:23 -03:00
if ( BookmarksBarWidget : : the ( ) . contains_bookmark ( url ) ) {
2022-01-11 00:06:11 -03:00
m_bookmark_button - > set_icon ( g_icon_bag . bookmark_filled ) ;
2023-08-01 15:31:54 -03:00
m_bookmark_button - > set_tooltip_deprecated ( " Remove Bookmark " ) ;
2020-04-23 16:14:31 -03:00
} else {
2022-01-11 00:06:11 -03:00
m_bookmark_button - > set_icon ( g_icon_bag . bookmark_contour ) ;
2023-08-01 15:31:54 -03:00
m_bookmark_button - > set_tooltip_deprecated ( " Add Bookmark " ) ;
2020-04-23 16:14:31 -03:00
}
}
void Tab : : did_become_active ( )
{
2022-12-21 04:28:00 -03:00
BookmarksBarWidget : : the ( ) . on_bookmark_click = [ this ] ( auto & url , auto open ) {
if ( open = = BookmarksBarWidget : : Open : : InNewTab )
2020-05-12 15:35:45 -03:00
on_tab_open_request ( url ) ;
2022-12-21 04:28:00 -03:00
else if ( open = = BookmarksBarWidget : : Open : : InNewWindow )
on_window_open_request ( url ) ;
2020-05-12 15:35:45 -03:00
else
2020-07-06 16:46:37 -03:00
load ( url ) ;
2020-04-25 12:20:23 -03:00
} ;
BookmarksBarWidget : : the ( ) . on_bookmark_hover = [ this ] ( auto & , auto & url ) {
2023-06-04 05:24:38 -03:00
m_statusbar - > set_text ( String : : from_deprecated_string ( url ) . release_value_but_fixme_should_propagate_errors ( ) ) ;
2020-04-25 12:20:23 -03:00
} ;
2023-03-29 23:36:57 -03:00
BookmarksBarWidget : : the ( ) . on_bookmark_change = [ this ] ( ) {
update_bookmark_button ( url ( ) . to_deprecated_string ( ) ) ;
2023-02-24 06:10:57 -03:00
} ;
2020-04-25 12:20:23 -03:00
BookmarksBarWidget : : the ( ) . remove_from_parent ( ) ;
m_toolbar_container - > add_child ( BookmarksBarWidget : : the ( ) ) ;
2021-05-18 14:23:53 -03:00
auto is_fullscreen = window ( ) . is_fullscreen ( ) ;
2020-05-19 12:11:01 -03:00
m_toolbar_container - > set_visible ( ! is_fullscreen ) ;
m_statusbar - > set_visible ( ! is_fullscreen ) ;
2021-05-18 14:23:53 -03:00
update_actions ( ) ;
2020-04-23 16:14:31 -03:00
}
2022-12-06 17:27:44 -03:00
void Tab : : context_menu_requested ( Gfx : : IntPoint screen_position )
2020-05-18 19:37:12 -03:00
{
m_tab_context_menu - > popup ( screen_position ) ;
}
2022-01-31 16:43:18 -03:00
void Tab : : content_filters_changed ( )
{
2022-02-01 07:17:37 -03:00
if ( g_content_filters_enabled )
m_web_content_view - > set_content_filters ( g_content_filters ) ;
else
m_web_content_view - > set_content_filters ( { } ) ;
2022-01-31 16:43:18 -03:00
}
2023-04-17 14:37:36 -03:00
void Tab : : autoplay_allowlist_changed ( )
{
if ( g_autoplay_allowed_on_all_websites )
m_web_content_view - > set_autoplay_allowed_on_all_websites ( ) ;
else
m_web_content_view - > set_autoplay_allowlist ( g_autoplay_allowlist ) ;
}
2022-04-07 18:16:47 -03:00
void Tab : : proxy_mappings_changed ( )
{
m_web_content_view - > set_proxy_mappings ( g_proxies , g_proxy_mappings ) ;
}
2021-04-17 17:08:06 -03:00
void Tab : : action_entered ( GUI : : Action & action )
{
2021-04-17 19:43:04 -03:00
m_statusbar - > set_override_text ( action . status_tip ( ) ) ;
2021-04-17 17:08:06 -03:00
}
2021-04-17 19:43:04 -03:00
void Tab : : action_left ( GUI : : Action & )
2021-04-17 17:08:06 -03:00
{
2021-04-17 19:43:04 -03:00
m_statusbar - > set_override_text ( { } ) ;
2021-04-17 17:08:06 -03:00
}
2022-12-06 17:27:44 -03:00
void Tab : : window_position_changed ( Gfx : : IntPoint position )
2022-11-01 16:43:53 -03:00
{
m_web_content_view - > set_window_position ( position ) ;
}
2022-12-06 18:35:32 -03:00
void Tab : : window_size_changed ( Gfx : : IntSize size )
2022-11-01 16:43:53 -03:00
{
m_web_content_view - > set_window_size ( size ) ;
}
2021-05-18 14:23:53 -03:00
BrowserWindow const & Tab : : window ( ) const
{
return static_cast < BrowserWindow const & > ( * Widget : : window ( ) ) ;
}
BrowserWindow & Tab : : window ( )
{
return static_cast < BrowserWindow & > ( * Widget : : window ( ) ) ;
}
2021-08-27 13:40:25 -03:00
void Tab : : show_inspector_window ( Browser : : Tab : : InspectorTarget inspector_target )
2021-08-17 13:00:27 -03:00
{
2021-08-23 12:16:08 -03:00
if ( ! m_dom_inspector_widget ) {
auto window = GUI : : Window : : construct ( & this - > window ( ) ) ;
2022-08-22 16:30:52 -03:00
window - > set_window_mode ( GUI : : WindowMode : : Modeless ) ;
2023-05-21 10:52:03 -03:00
window - > resize ( 325 , 500 ) ;
2021-09-13 15:24:59 -03:00
window - > set_title ( " Inspector " ) ;
2022-01-11 00:06:11 -03:00
window - > set_icon ( g_icon_bag . inspector_object ) ;
2021-08-23 12:16:08 -03:00
window - > on_close = [ & ] ( ) {
2021-09-02 08:05:32 -03:00
m_web_content_view - > clear_inspected_dom_node ( ) ;
2021-08-23 12:16:08 -03:00
} ;
2023-09-18 21:13:48 -03:00
m_dom_inspector_widget = window - > set_main_widget < InspectorWidget > ( ) ;
2021-09-02 08:05:32 -03:00
m_dom_inspector_widget - > set_web_view ( * m_web_content_view ) ;
2021-09-01 08:50:47 -03:00
m_web_content_view - > inspect_dom_tree ( ) ;
2022-12-28 20:26:23 -03:00
m_web_content_view - > inspect_accessibility_tree ( ) ;
2021-08-23 12:16:08 -03:00
}
2021-08-27 13:40:25 -03:00
if ( inspector_target = = InspectorTarget : : HoveredElement ) {
2022-03-04 13:16:57 -03:00
// FIXME: Handle pseudo-elements
auto hovered_node = m_web_content_view - > get_hovered_node_id ( ) ;
m_dom_inspector_widget - > set_selection ( { hovered_node } ) ;
2021-08-27 16:21:30 -03:00
} else {
VERIFY ( inspector_target = = InspectorTarget : : Document ) ;
m_dom_inspector_widget - > select_default_node ( ) ;
2021-08-27 13:40:25 -03:00
}
2021-08-23 12:16:08 -03:00
auto * window = m_dom_inspector_widget - > window ( ) ;
window - > show ( ) ;
window - > move_to_front ( ) ;
2021-08-17 13:00:27 -03:00
}
2022-12-18 19:45:05 -03:00
void Tab : : close_sub_widgets ( )
{
auto close_widget_window = [ ] ( auto & widget ) {
if ( widget ) {
auto * window = widget - > window ( ) ;
window - > close ( ) ;
}
} ;
close_widget_window ( m_dom_inspector_widget ) ;
close_widget_window ( m_console_widget ) ;
close_widget_window ( m_storage_widget ) ;
}
2021-09-01 13:03:18 -03:00
void Tab : : show_console_window ( )
{
if ( ! m_console_widget ) {
auto console_window = GUI : : Window : : construct ( & window ( ) ) ;
console_window - > resize ( 500 , 300 ) ;
console_window - > set_title ( " JS Console " ) ;
2022-01-11 00:06:11 -03:00
console_window - > set_icon ( g_icon_bag . filetype_javascript ) ;
2023-08-29 12:44:18 -03:00
2023-09-18 21:13:48 -03:00
m_console_widget = console_window - > set_main_widget < ConsoleWidget > ( view ( ) ) ;
2021-09-01 13:03:18 -03:00
}
auto * window = m_console_widget - > window ( ) ;
window - > show ( ) ;
window - > move_to_front ( ) ;
}
2022-03-01 13:10:06 -03:00
void Tab : : show_storage_inspector ( )
{
if ( ! m_storage_widget ) {
auto storage_window = GUI : : Window : : construct ( & window ( ) ) ;
storage_window - > resize ( 500 , 300 ) ;
2023-05-22 14:07:09 -03:00
storage_window - > set_title ( " Storage Inspector " ) ;
2022-03-01 13:10:06 -03:00
storage_window - > set_icon ( g_icon_bag . cookie ) ;
2023-09-18 21:13:48 -03:00
m_storage_widget = storage_window - > set_main_widget < StorageWidget > ( ) ;
2022-10-20 12:38:20 -03:00
m_storage_widget - > on_update_cookie = [ this ] ( Web : : Cookie : : Cookie cookie ) {
if ( on_update_cookie )
2022-11-28 13:24:04 -03:00
on_update_cookie ( move ( cookie ) ) ;
2022-10-20 12:38:20 -03:00
} ;
2022-03-01 13:10:06 -03:00
}
2022-05-04 16:51:15 -03:00
if ( on_get_cookies_entries ) {
auto cookies = on_get_cookies_entries ( ) ;
2022-03-01 13:10:06 -03:00
m_storage_widget - > clear_cookies ( ) ;
2022-05-04 16:53:01 -03:00
m_storage_widget - > set_cookies_entries ( cookies ) ;
2022-03-01 13:10:06 -03:00
}
2022-04-01 18:14:04 -03:00
if ( on_get_local_storage_entries ) {
auto local_storage_entries = on_get_local_storage_entries ( ) ;
m_storage_widget - > clear_local_storage_entries ( ) ;
2023-06-07 06:36:56 -03:00
m_storage_widget - > set_local_storage_entries ( move ( local_storage_entries ) ) ;
2022-04-01 18:14:04 -03:00
}
2022-05-07 17:45:43 -03:00
if ( on_get_session_storage_entries ) {
auto session_storage_entries = on_get_session_storage_entries ( ) ;
m_storage_widget - > clear_session_storage_entries ( ) ;
2023-06-07 06:36:56 -03:00
m_storage_widget - > set_session_storage_entries ( move ( session_storage_entries ) ) ;
2022-05-07 17:45:43 -03:00
}
2022-03-01 13:10:06 -03:00
auto * window = m_storage_widget - > window ( ) ;
window - > show ( ) ;
window - > move_to_front ( ) ;
}
2022-12-10 12:50:47 -03:00
void Tab : : show_history_inspector ( )
{
if ( ! m_history_widget ) {
auto history_window = GUI : : Window : : construct ( & window ( ) ) ;
history_window - > resize ( 500 , 300 ) ;
history_window - > set_title ( " History " ) ;
history_window - > set_icon ( g_icon_bag . history ) ;
2023-09-18 21:13:48 -03:00
m_history_widget = history_window - > set_main_widget < HistoryWidget > ( ) ;
2022-12-10 12:50:47 -03:00
}
m_history_widget - > clear_history_entries ( ) ;
m_history_widget - > set_history_entries ( m_history . get_all_history_entries ( ) ) ;
auto * window = m_history_widget - > window ( ) ;
window - > show ( ) ;
window - > move_to_front ( ) ;
}
2022-09-19 15:50:33 -03:00
void Tab : : show_event ( GUI : : ShowEvent & )
{
m_web_content_view - > set_visible ( true ) ;
}
void Tab : : hide_event ( GUI : : HideEvent & )
{
m_web_content_view - > set_visible ( false ) ;
}
2022-11-04 21:59:10 -03:00
void Tab : : enable_webdriver_mode ( )
{
2022-11-08 12:18:11 -03:00
m_web_content_view - > connect_to_webdriver ( Browser : : g_webdriver_content_ipc_path ) ;
2022-11-04 22:00:09 -03:00
auto & webdriver_banner = * find_descendant_of_type_named < GUI : : Widget > ( " webdriver_banner " ) ;
webdriver_banner . set_visible ( true ) ;
2022-11-04 21:59:10 -03:00
}
2020-04-23 16:14:31 -03:00
}