|
4 | 4 | * SPDX-License-Identifier: BSD-2-Clause
|
5 | 5 | */
|
6 | 6 |
|
| 7 | +#include <AK/Enumerate.h> |
7 | 8 | #include <BrowserSettings/Defaults.h>
|
8 | 9 | #include <Ladybird/MachPortServer.h>
|
9 | 10 | #include <Ladybird/Types.h>
|
|
12 | 13 | #include <LibCore/EventLoop.h>
|
13 | 14 | #include <LibGfx/Font/FontDatabase.h>
|
14 | 15 | #include <LibMain/Main.h>
|
| 16 | +#include <LibWebView/ChromeProcess.h> |
15 | 17 | #include <LibWebView/CookieJar.h>
|
16 | 18 | #include <LibWebView/Database.h>
|
17 | 19 | #include <LibWebView/ProcessManager.h>
|
|
27 | 29 | # error "This project requires ARC"
|
28 | 30 | #endif
|
29 | 31 |
|
| 32 | +static Vector<URL::URL> sanitize_urls(Vector<ByteString> const& raw_urls) |
| 33 | +{ |
| 34 | + Vector<URL::URL> sanitized_urls; |
| 35 | + for (auto const& raw_url : raw_urls) { |
| 36 | + if (auto url = WebView::sanitize_url(raw_url); url.has_value()) |
| 37 | + sanitized_urls.append(url.release_value()); |
| 38 | + } |
| 39 | + |
| 40 | + if (sanitized_urls.is_empty()) { |
| 41 | + URL::URL new_tab_page_url = Browser::default_new_tab_url; |
| 42 | + sanitized_urls.append(move(new_tab_page_url)); |
| 43 | + } |
| 44 | + |
| 45 | + return sanitized_urls; |
| 46 | +} |
| 47 | + |
| 48 | +enum class NewWindow { |
| 49 | + No, |
| 50 | + Yes, |
| 51 | +}; |
| 52 | + |
| 53 | +static void open_urls_from_client(Vector<ByteString> const& raw_urls, NewWindow new_window) |
| 54 | +{ |
| 55 | + ApplicationDelegate* delegate = [NSApp delegate]; |
| 56 | + Tab* tab = new_window == NewWindow::Yes ? nil : [delegate activeTab]; |
| 57 | + |
| 58 | + auto urls = sanitize_urls(raw_urls); |
| 59 | + |
| 60 | + for (auto [i, url] : enumerate(urls)) { |
| 61 | + auto activate_tab = i == 0 ? Web::HTML::ActivateTab::Yes : Web::HTML::ActivateTab::No; |
| 62 | + |
| 63 | + auto* controller = [delegate createNewTab:url |
| 64 | + fromTab:tab |
| 65 | + activateTab:activate_tab]; |
| 66 | + |
| 67 | + tab = (Tab*)[controller window]; |
| 68 | + } |
| 69 | +} |
| 70 | + |
30 | 71 | ErrorOr<int> serenity_main(Main::Arguments arguments)
|
31 | 72 | {
|
32 | 73 | AK::set_rich_debug_enabled(true);
|
|
42 | 83 | Gfx::FontDatabase::set_default_font_query("Katica 10 400 0");
|
43 | 84 | Gfx::FontDatabase::set_fixed_width_font_query("Csilla 10 400 0");
|
44 | 85 |
|
45 |
| - Vector<StringView> raw_urls; |
| 86 | + Vector<ByteString> raw_urls; |
46 | 87 | Vector<ByteString> certificates;
|
47 | 88 | StringView webdriver_content_ipc_path;
|
48 | 89 | bool use_gpu_painting = false;
|
49 | 90 | bool debug_web_content = false;
|
50 | 91 | bool log_all_js_exceptions = false;
|
| 92 | + bool new_window = false; |
51 | 93 |
|
52 | 94 | Core::ArgsParser args_parser;
|
53 | 95 | args_parser.set_general_help("The Ladybird web browser");
|
|
57 | 99 | args_parser.add_option(debug_web_content, "Wait for debugger to attach to WebContent", "debug-web-content");
|
58 | 100 | args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
|
59 | 101 | args_parser.add_option(log_all_js_exceptions, "Log all JavaScript exceptions", "log-all-js-exceptions");
|
| 102 | + args_parser.add_option(new_window, "Force opening in a new window", "new-window", 'n'); |
60 | 103 | args_parser.parse(arguments);
|
61 | 104 |
|
| 105 | + WebView::ChromeProcess chrome_process; |
| 106 | + if (TRY(chrome_process.connect(raw_urls, new_window)) == WebView::ChromeProcess::ProcessDisposition::ExitProcess) { |
| 107 | + outln("Opening in existing process"); |
| 108 | + return 0; |
| 109 | + } |
| 110 | + |
| 111 | + chrome_process.on_new_tab = [&](auto const& raw_urls) { |
| 112 | + open_urls_from_client(raw_urls, NewWindow::No); |
| 113 | + }; |
| 114 | + |
| 115 | + chrome_process.on_new_window = [&](auto const& raw_urls) { |
| 116 | + open_urls_from_client(raw_urls, NewWindow::Yes); |
| 117 | + }; |
| 118 | + |
62 | 119 | WebView::ProcessManager::initialize();
|
63 | 120 |
|
64 | 121 | auto mach_port_server = make<Ladybird::MachPortServer>();
|
|
74 | 131 | // FIXME: Create an abstraction to re-spawn the RequestServer and re-hook up its client hooks to each tab on crash
|
75 | 132 | TRY([application launchRequestServer:certificates]);
|
76 | 133 |
|
77 |
| - URL::URL new_tab_page_url = Browser::default_new_tab_url; |
78 |
| - Vector<URL::URL> initial_urls; |
79 |
| - |
80 |
| - for (auto const& raw_url : raw_urls) { |
81 |
| - if (auto url = WebView::sanitize_url(raw_url); url.has_value()) |
82 |
| - initial_urls.append(url.release_value()); |
83 |
| - } |
84 |
| - |
85 |
| - if (initial_urls.is_empty()) |
86 |
| - initial_urls.append(new_tab_page_url); |
87 |
| - |
88 | 134 | StringBuilder command_line_builder;
|
89 | 135 | command_line_builder.join(' ', arguments.strings);
|
90 | 136 | Ladybird::WebContentOptions web_content_options {
|
|
95 | 141 | .log_all_js_exceptions = log_all_js_exceptions ? Ladybird::LogAllJSExceptions::Yes : Ladybird::LogAllJSExceptions::No,
|
96 | 142 | };
|
97 | 143 |
|
98 |
| - auto* delegate = [[ApplicationDelegate alloc] init:move(initial_urls) |
99 |
| - newTabPageURL:move(new_tab_page_url) |
| 144 | + auto* delegate = [[ApplicationDelegate alloc] init:sanitize_urls(raw_urls) |
| 145 | + newTabPageURL:URL::URL { Browser::default_new_tab_url } |
100 | 146 | withCookieJar:move(cookie_jar)
|
101 | 147 | webContentOptions:web_content_options
|
102 | 148 | webdriverContentIPCPath:webdriver_content_ipc_path];
|
|
0 commit comments