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 >
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"
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>
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>
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>
2020-05-23 13:53:09 -03:00
# include <LibJS/Interpreter.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>
2021-09-08 06:27:46 -03:00
# include <LibWeb/Layout/InitialContainingBlock.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-02-06 12:29:49 -03:00
URL url_from_user_input ( String const & input )
2020-06-12 16:29:27 -03:00
{
2022-07-11 14:32:29 -03:00
if ( input . starts_with ( ' ? ' ) & & ! g_search_engine . is_empty ( ) )
return URL ( g_search_engine . replace ( " {} " sv , URL : : percent_encode ( input . substring_view ( 1 ) ) , ReplaceMode : : FirstOnly ) ) ;
2021-04-26 06:52:19 -03:00
2022-02-06 12:29:49 -03:00
URL url_with_http_schema = URL ( String : : formatted ( " http://{} " , input ) ) ;
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 ) ;
2020-10-04 07:39:02 -03:00
window - > set_title ( String : : formatted ( " 0% of {} " , url . basename ( ) ) ) ;
2020-10-02 14:00:45 -03:00
window - > set_resizable ( false ) ;
window - > set_main_widget < DownloadWidget > ( url ) ;
window - > show ( ) ;
}
2022-04-01 14:58:27 -03:00
void Tab : : view_source ( const URL & url , String 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 ( ) ) ;
2021-02-23 09:18:22 -03:00
auto & editor = window - > set_main_widget < GUI : : TextEditor > ( ) ;
editor . set_text ( source ) ;
editor . set_mode ( GUI : : TextEditor : : ReadOnly ) ;
2021-05-20 15:47:30 -03:00
editor . set_syntax_highlighter ( make < Web : : HTML : : SyntaxHighlighter > ( ) ) ;
2021-02-23 09:18:22 -03:00
editor . set_ruler_visible ( true ) ;
window - > resize ( 640 , 480 ) ;
2021-03-27 07:12:35 -03:00
window - > set_title ( url . to_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 ( ) ;
}
2022-02-20 19:03:39 -03:00
void Tab : : update_status ( Optional < String > text_override , i32 count_waiting )
{
if ( text_override . has_value ( ) ) {
m_statusbar - > set_text ( * text_override ) ;
return ;
}
if ( m_loaded ) {
m_statusbar - > set_text ( " " ) ;
return ;
}
VERIFY ( m_navigating_url . has_value ( ) ) ;
if ( count_waiting = = 0 ) {
// ex: "Loading google.com"
m_statusbar - > set_text ( String : : formatted ( " Loading {} " , m_navigating_url - > host ( ) ) ) ;
} else {
// ex: "google.com is waiting on 5 resources"
m_statusbar - > set_text ( String : : formatted ( " {} is waiting on {} resource{} " , m_navigating_url - > host ( ) , count_waiting , count_waiting = = 1 ? " " sv : " s " sv ) ) ;
}
}
2021-08-24 11:35:46 -03:00
Tab : : Tab ( BrowserWindow & window )
2020-04-23 16:14:31 -03:00
{
2020-12-20 07:47:44 -03:00
load_from_gml ( tab_gml ) ;
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
2022-04-30 05:46:33 -03:00
m_web_content_view = webview_container . add < WebView : : OutOfProcessWebView > ( ) ;
2022-07-31 18:38:55 -03:00
auto preferred_color_scheme = Web : : CSS : : preferred_color_scheme_from_string ( Config : : read_string ( " Browser " sv , " Preferences " sv , " ColorScheme " sv , " auto " sv ) ) ;
m_web_content_view - > set_preferred_color_scheme ( preferred_color_scheme ) ;
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 ( { } ) ;
2020-04-23 16:14:31 -03:00
2022-04-07 18:16:47 -03:00
m_web_content_view - > set_proxy_mappings ( g_proxies , g_proxy_mappings ) ;
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-01-11 00:06:11 -03:00
m_go_back_context_menu - > add_action ( GUI : : Action : : create ( url . to_string ( ) , g_icon_bag . filetype_html , [ this , i ] ( auto & ) { go_back ( i ) ; } ) ) ;
2021-05-23 19:58:00 -03:00
}
2022-08-04 19:53:44 -03:00
m_go_back_context_menu - > popup ( go_back_button . screen_relative_rect ( ) . bottom_left ( ) ) ;
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-01-11 00:06:11 -03:00
m_go_forward_context_menu - > add_action ( GUI : : Action : : create ( url . to_string ( ) , g_icon_bag . filetype_html , [ this , i ] ( auto & ) { go_forward ( i ) ; } ) ) ;
2021-05-23 19:58:00 -03:00
}
2022-08-04 19:53:44 -03:00
m_go_forward_context_menu - > popup ( go_forward_button . screen_relative_rect ( ) . bottom_left ( ) ) ;
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 > ( ) ;
2022-07-11 14:32:29 -03:00
m_location_box - > set_placeholder ( " 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 & ) {
bookmark_current_url ( ) ;
} ,
this ) ;
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-04-06 10:15:07 -03:00
view ( ) . on_load_start = [ this ] ( auto & url ) {
2022-02-20 19:03:39 -03:00
m_navigating_url = url ;
m_loaded = false ;
update_status ( ) ;
2020-06-30 16:11:35 -03:00
m_location_box - > set_icon ( nullptr ) ;
2020-04-23 16:14:31 -03:00
m_location_box - > set_text ( url . to_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 ( ) ;
update_bookmark_button ( url . to_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 ( ) ;
2021-09-01 08:50:47 -03:00
if ( m_dom_inspector_widget )
m_web_content_view - > inspect_dom_tree ( ) ;
2020-04-23 16:14:31 -03:00
} ;
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 ) ;
} ;
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 & ) {
2020-09-05 11:16:01 -03:00
GUI : : Clipboard : : the ( ) . set_plain_text ( m_link_context_menu_url . to_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
2022-04-06 10:15:07 -03:00
view ( ) . on_link_context_menu_request = [ this ] ( auto & url , auto & screen_position ) {
2020-07-06 15:00:56 -03:00
m_link_context_menu_url = url ;
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 & ) {
2020-10-02 14:03:10 -03:00
GUI : : Clipboard : : the ( ) . set_plain_text ( m_image_context_menu_url . to_string ( ) ) ;
} ) ) ;
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
2022-04-06 10:15:07 -03:00
view ( ) . on_image_context_menu_request = [ this ] ( auto & image_url , auto & screen_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 ;
m_image_context_menu - > popup ( screen_position ) ;
} ;
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
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_title_change = [ this ] ( auto & title ) {
2020-04-23 16:14:31 -03:00
if ( title . is_null ( ) ) {
2021-05-26 15:19:35 -03:00
m_history . update_title ( url ( ) . to_string ( ) ) ;
2020-07-06 16:46:37 -03:00
m_title = url ( ) . to_string ( ) ;
2020-04-23 16:14:31 -03:00
} else {
2021-05-26 15:19:35 -03:00
m_history . update_title ( title ) ;
2020-04-23 16:14:31 -03:00
m_title = title ;
}
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-04-06 10:15:07 -03:00
view ( ) . on_get_cookie = [ this ] ( auto & url , auto source ) - > String {
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-04-06 10:15:07 -03:00
view ( ) . on_get_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
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_get_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
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_get_dom_node_properties = [ this ] ( auto node_id , auto & specified , auto & computed , auto & custom_properties , auto & node_box_sizing ) {
2022-03-04 13:16:57 -03:00
m_dom_inspector_widget - > set_dom_node_properties_json ( { node_id } , specified , computed , custom_properties , node_box_sizing ) ;
2021-08-27 08:47:30 -03:00
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_js_console_new_message = [ this ] ( auto message_index ) {
2021-09-01 13:03:18 -03:00
if ( m_console_widget )
2021-09-04 08:12:12 -03:00
m_console_widget - > notify_about_new_console_message ( message_index ) ;
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_get_js_console_messages = [ this ] ( auto start_index , auto & message_types , auto & messages ) {
2021-09-04 08:12:12 -03:00
if ( m_console_widget )
m_console_widget - > handle_console_messages ( start_index , message_types , messages ) ;
2021-02-28 00:53:20 -03:00
} ;
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 ) {
2020-07-05 12:02:44 -03:00
if ( url . is_valid ( ) )
2022-02-20 19:03:39 -03:00
update_status ( url . to_string ( ) ) ;
2020-07-05 12:02:44 -03:00
else
2022-02-20 19:03:39 -03:00
update_status ( ) ;
2020-04-23 16:14:31 -03:00
} ;
2022-04-06 10:15:07 -03:00
view ( ) . on_url_drop = [ this ] ( auto & url ) {
2020-07-06 16:46:37 -03:00
load ( url ) ;
2020-05-10 16:04:37 -03:00
} ;
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
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 ( ) ;
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 ( ) ) ;
2022-04-06 10:15:07 -03:00
view ( ) . on_context_menu_request = [ & ] ( auto & screen_position ) {
2020-06-27 17:23:21 -03:00
m_page_context_menu - > popup ( screen_position ) ;
} ;
2020-04-23 16:14:31 -03:00
}
2022-03-19 08:10:38 -03:00
Optional < URL > Tab : : url_from_location_bar ( MayAppendTLD may_append_tld )
{
if ( m_location_box - > text ( ) . starts_with ( ' ? ' ) & & g_search_engine . is_empty ( ) ) {
2022-07-11 14:32:29 -03:00
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 ) ;
2022-03-19 08:10:38 -03:00
return { } ;
}
String text = m_location_box - > text ( ) ;
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
}
}
String final_text = builder . to_string ( ) ;
auto url = url_from_user_input ( final_text ) ;
return url ;
}
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 ( )
{
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
{
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
{
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 ( ) ) ;
2020-04-23 16:14:31 -03:00
}
2021-08-15 02:52:27 -03:00
void Tab : : bookmark_current_url ( )
{
auto url = this - > url ( ) . to_string ( ) ;
if ( BookmarksBarWidget : : the ( ) . contains_bookmark ( url ) ) {
BookmarksBarWidget : : the ( ) . remove_bookmark ( url ) ;
} else {
BookmarksBarWidget : : the ( ) . add_bookmark ( url , m_title ) ;
}
update_bookmark_button ( url ) ;
}
2022-04-01 14:58:27 -03:00
void Tab : : update_bookmark_button ( String const & 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 ) ;
2020-04-30 00:41:48 -03:00
m_bookmark_button - > set_tooltip ( " 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 ) ;
2020-04-30 00:41:48 -03:00
m_bookmark_button - > set_tooltip ( " Add Bookmark " ) ;
2020-04-23 16:14:31 -03:00
}
}
void Tab : : did_become_active ( )
{
2022-07-10 11:29:35 -03:00
BookmarksBarWidget : : the ( ) . on_bookmark_click = [ this ] ( auto & url , auto open_in_new_tab ) {
if ( open_in_new_tab = = BookmarksBarWidget : : OpenInNewTab : : Yes )
2020-05-12 15:35:45 -03:00
on_tab_open_request ( url ) ;
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 ) {
m_statusbar - > set_text ( url ) ;
} ;
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-04-01 14:58:27 -03:00
void Tab : : context_menu_requested ( Gfx : : IntPoint const & 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
}
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
}
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 ) ;
2021-08-23 12:16:08 -03:00
window - > resize ( 300 , 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
} ;
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 ( ) ;
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
}
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 ) ;
2021-09-01 13:03:18 -03:00
m_console_widget = console_window - > set_main_widget < ConsoleWidget > ( ) ;
m_console_widget - > on_js_input = [ this ] ( String const & js_source ) {
m_web_content_view - > js_console_input ( js_source ) ;
} ;
2021-09-04 08:12:12 -03:00
m_console_widget - > on_request_messages = [ this ] ( i32 start_index ) {
m_web_content_view - > js_console_request_messages ( start_index ) ;
} ;
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 ) ;
storage_window - > set_title ( " Storage inspector " ) ;
storage_window - > set_icon ( g_icon_bag . cookie ) ;
m_storage_widget = storage_window - > set_main_widget < StorageWidget > ( ) ;
}
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 ( ) ;
m_storage_widget - > set_local_storage_entries ( local_storage_entries ) ;
}
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 ( ) ;
m_storage_widget - > set_session_storage_entries ( session_storage_entries ) ;
}
2022-03-01 13:10:06 -03:00
auto * window = m_storage_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 ) ;
}
2020-04-23 16:14:31 -03:00
}