blob: b39a6f0a4cbbcc99fa3543c2477c5f5f873b7f34 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[email protected]9fbd3f862011-09-20 23:31:342// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]de7d61ff2013-08-20 11:30:415#include "content/shell/browser/shell.h"
[email protected]9fbd3f862011-09-20 23:31:346
avi66a07722015-12-25 23:38:127#include <stddef.h>
8
Lukasz Anforowicz52b93722018-06-20 16:11:399#include <map>
Peter Boströmdd7e40ec2021-04-05 20:40:1010#include <memory>
Lukasz Anforowicz52b93722018-06-20 16:11:3911#include <string>
12#include <utility>
13
[email protected]efb5f572012-01-29 10:57:3314#include "base/command_line.h"
Avi Drissmanadac21992023-01-11 23:46:3915#include "base/functional/callback_helpers.h"
skyostil95082a62015-06-05 19:53:0716#include "base/location.h"
Wez9a58a152018-06-07 18:59:3317#include "base/no_destructor.h"
fdoray896bea12016-06-10 15:52:0118#include "base/run_loop.h"
[email protected]21aa99682013-06-11 07:17:0119#include "base/strings/string_number_conversions.h"
20#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0021#include "base/strings/utf_string_conversions.h"
avi66a07722015-12-25 23:38:1222#include "build/build_config.h"
Javier Fernández García-Boente13150a042022-04-04 21:08:2223#include "components/custom_handlers/protocol_handler.h"
24#include "components/custom_handlers/protocol_handler_registry.h"
25#include "components/custom_handlers/simple_protocol_handler_registry_factory.h"
26#include "content/public/browser/browser_context.h"
[email protected]b50452f2014-08-18 12:31:4427#include "content/public/browser/devtools_agent_host.h"
Julie Jeongeun Kimec508272023-03-17 04:17:1228#include "content/public/browser/file_select_listener.h"
[email protected]0b659b32012-03-26 21:29:3229#include "content/public/browser/navigation_controller.h"
[email protected]b7c504c2013-05-07 14:42:1230#include "content/public/browser/navigation_entry.h"
Becca Hughes112832e2019-06-11 17:19:0231#include "content/public/browser/picture_in_picture_window_controller.h"
arthursonzognib93a4472020-04-10 07:38:0032#include "content/public/browser/presentation_receiver_flags.h"
Yutaka Hirano2109e582018-02-14 07:24:4633#include "content/public/browser/render_process_host.h"
[email protected]0b659b32012-03-26 21:29:3234#include "content/public/browser/render_view_host.h"
avif9ab5d942015-10-15 14:05:4435#include "content/public/browser/render_widget_host.h"
Xianzhu Wang6be66b012020-05-06 17:17:2536#include "content/public/browser/renderer_preferences_util.h"
[email protected]0b659b32012-03-26 21:29:3237#include "content/public/browser/web_contents.h"
guoweis8efb6d892015-10-12 18:26:1738#include "content/public/common/content_switches.h"
danakjde3e2a02020-05-12 16:51:2039#include "content/shell/app/resource.h"
[email protected]de7d61ff2013-08-20 11:30:4140#include "content/shell/browser/shell_content_browser_client.h"
41#include "content/shell/browser/shell_devtools_frontend.h"
42#include "content/shell/browser/shell_javascript_dialog_manager.h"
[email protected]b7c504c2013-05-07 14:42:1243#include "content/shell/common/shell_switches.h"
Scott Violeta35f9a42018-03-22 22:00:4444#include "media/media_buildflags.h"
Antonio Gomesb5bf548f2019-09-12 17:40:1545#include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
Mario Sanchez Prada0bd8b8c2020-10-21 17:49:2346#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
Julie Jeongeun Kimec508272023-03-17 04:17:1247#include "third_party/blink/public/mojom/choosers/file_chooser.mojom-forward.h"
Brad Triebwasser767c27a2022-08-25 22:56:0548#include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
[email protected]9fbd3f862011-09-20 23:31:3449
[email protected]9fbd3f862011-09-20 23:31:3450namespace content {
51
arthursonzogni75ede192021-07-06 14:45:4652namespace {
Wezcbf4a042018-06-13 16:29:1253// Null until/unless the default main message loop is running.
Lei Zhangebdd085d2022-10-25 17:24:2654base::OnceClosure& GetMainMessageLoopQuitClosure() {
55 static base::NoDestructor<base::OnceClosure> closure;
56 return *closure;
57}
Wez9a58a152018-06-07 18:59:3358
Lei Zhangebdd085d2022-10-25 17:24:2659constexpr int kDefaultTestWindowWidthDip = 800;
60constexpr int kDefaultTestWindowHeightDip = 600;
[email protected]1e57cab2013-05-28 04:26:1161
arthursonzogni75ede192021-07-06 14:45:4662// Owning pointer. We can not use unique_ptr as a global. That introduces a
63// static constructor/destructor.
64// Acquired in Shell::Init(), released in Shell::Shutdown().
65ShellPlatformDelegate* g_platform;
66} // namespace
67
[email protected]e99ca5112011-09-26 17:22:5468std::vector<Shell*> Shell::windows_;
danakja9fe91c2019-05-01 19:02:2969base::OnceCallback<void(Shell*)> Shell::shell_created_callback_;
[email protected]9fbd3f862011-09-20 23:31:3470
Bo Liu300c6052018-06-12 04:46:0771Shell::Shell(std::unique_ptr<WebContents> web_contents,
72 bool should_set_delegate)
erikchenbee5c9622018-04-27 19:30:2573 : WebContentsObserver(web_contents.get()),
danakjde3e2a02020-05-12 16:51:2074 web_contents_(std::move(web_contents)) {
Bo Liu300c6052018-06-12 04:46:0775 if (should_set_delegate)
76 web_contents_->SetDelegate(this);
arthursonzognifdd49912017-08-31 08:55:2677
danakjd4b48df52020-07-02 18:16:4878 if (!switches::IsRunWebTestsSwitchPresent()) {
Xianzhu Wang6be66b012020-05-06 17:17:2579 UpdateFontRendererPreferencesFromSystemSettings(
80 web_contents_->GetMutableRendererPrefs());
Francois Doraye6161152018-03-27 22:05:3781 }
Pavel Feldmanc7cd063c2017-10-06 20:04:2882
[email protected]9e00e6352012-07-30 17:05:1883 windows_.push_back(this);
84
danakja9fe91c2019-05-01 19:02:2985 if (shell_created_callback_)
86 std::move(shell_created_callback_).Run(this);
[email protected]9fbd3f862011-09-20 23:31:3487}
88
89Shell::~Shell() {
danakjde3e2a02020-05-12 16:51:2090 g_platform->CleanUp(this);
[email protected]e99ca5112011-09-26 17:22:5491
92 for (size_t i = 0; i < windows_.size(); ++i) {
93 if (windows_[i] == this) {
94 windows_.erase(windows_.begin() + i);
95 break;
96 }
97 }
[email protected]11a65b692012-03-30 11:29:1698
Sergey Ulanovf0875d12019-01-03 20:33:2399 web_contents_->SetDelegate(nullptr);
100 web_contents_.reset();
Arthur Sonzogni9e72df3f2021-07-02 14:32:17101
arthursonzogni75ede192021-07-06 14:45:46102 if (windows().empty())
103 g_platform->DidCloseLastWindow();
[email protected]9fbd3f862011-09-20 23:31:34104}
105
erikchenbee5c9622018-04-27 19:30:25106Shell* Shell::CreateShell(std::unique_ptr<WebContents> web_contents,
Bo Liu300c6052018-06-12 04:46:07107 const gfx::Size& initial_size,
108 bool should_set_delegate) {
erikchenbee5c9622018-04-27 19:30:25109 WebContents* raw_web_contents = web_contents.get();
Bo Liu300c6052018-06-12 04:46:07110 Shell* shell = new Shell(std::move(web_contents), should_set_delegate);
danakjde3e2a02020-05-12 16:51:20111 g_platform->CreatePlatformWindow(shell, initial_size);
[email protected]1596efb2013-01-17 22:13:01112
creisb6561df2016-02-11 20:20:54113 // Note: Do not make RenderFrameHost or RenderViewHost specific state changes
114 // here, because they will be forgotten after a cross-process navigation. Use
115 // RenderFrameCreated or RenderViewCreated instead.
Kent Tamuracd3ebc42018-05-16 06:44:22116 if (switches::IsRunWebTestsSwitchPresent()) {
erikchenbee5c9622018-04-27 19:30:25117 raw_web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
Bruce Long1e3e1f542019-10-16 17:56:28118 raw_web_contents->SyncRendererPrefs();
[email protected]1596efb2013-01-17 22:13:01119 }
120
lukasza381b0492016-03-10 16:48:43121 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
guoweis4ee48592015-12-02 06:37:07122 if (command_line->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) {
erikchenbee5c9622018-04-27 19:30:25123 raw_web_contents->GetMutableRendererPrefs()->webrtc_ip_handling_policy =
guoweis4ee48592015-12-02 06:37:07124 command_line->GetSwitchValueASCII(
125 switches::kForceWebRtcIPHandlingPolicy);
guoweis8efb6d892015-10-12 18:26:17126 }
guoweis8efb6d892015-10-12 18:26:17127
danakj8de3b7492020-07-02 22:41:42128 g_platform->SetContents(shell);
129 g_platform->DidCreateOrAttachWebContents(shell, raw_web_contents);
danakj3dd7a6102020-12-30 19:58:39130 // If the RenderFrame was created during WebContents construction (as happens
131 // for windows opened from the renderer) then the Shell won't hear about the
132 // main frame being created as a WebContentsObservers. This gives the delegate
133 // a chance to act on the main frame accordingly.
Dave Tapuska327c06c92022-06-13 20:31:51134 if (raw_web_contents->GetPrimaryMainFrame()->IsRenderFrameLive())
danakj3dd7a6102020-12-30 19:58:39135 g_platform->MainFrameCreated(shell);
danakj7da833932020-06-23 21:49:40136
[email protected]3fd84032012-01-12 18:20:17137 return shell;
138}
139
arthursonzogni75ede192021-07-06 14:45:46140// static
Wezcbf4a042018-06-13 16:29:12141void Shell::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
Lei Zhangebdd085d2022-10-25 17:24:26142 GetMainMessageLoopQuitClosure() = std::move(quit_closure);
Wezcbf4a042018-06-13 16:29:12143}
144
arthursonzogni75ede192021-07-06 14:45:46145// static
Wez7d3eb012018-06-20 22:51:28146void Shell::QuitMainMessageLoopForTesting() {
Lei Zhangebdd085d2022-10-25 17:24:26147 auto& quit_loop = GetMainMessageLoopQuitClosure();
148 if (quit_loop)
149 std::move(quit_loop).Run();
Wez7d3eb012018-06-20 22:51:28150}
151
arthursonzogni75ede192021-07-06 14:45:46152// static
[email protected]9e00e6352012-07-30 17:05:18153void Shell::SetShellCreatedCallback(
danakja9fe91c2019-05-01 19:02:29154 base::OnceCallback<void(Shell*)> shell_created_callback) {
155 DCHECK(!shell_created_callback_);
Tommy Nyquist4b749d02018-03-20 21:46:29156 shell_created_callback_ = std::move(shell_created_callback);
[email protected]9e00e6352012-07-30 17:05:18157}
158
danakjde3e2a02020-05-12 16:51:20159// static
160bool Shell::ShouldHideToolbar() {
161 return base::CommandLine::ForCurrentProcess()->HasSwitch(
162 switches::kContentShellHideToolbar);
163}
164
arthursonzogni75ede192021-07-06 14:45:46165// static
David Benjaminf62c6662019-03-21 20:25:04166Shell* Shell::FromWebContents(WebContents* web_contents) {
167 for (Shell* window : windows_) {
168 if (window->web_contents() && window->web_contents() == web_contents) {
169 return window;
[email protected]74830f02012-01-30 22:27:04170 }
171 }
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28172 return nullptr;
[email protected]74830f02012-01-30 22:27:04173}
174
arthursonzogni75ede192021-07-06 14:45:46175// static
danakjde3e2a02020-05-12 16:51:20176void Shell::Initialize(std::unique_ptr<ShellPlatformDelegate> platform) {
arthursonzogni75ede192021-07-06 14:45:46177 DCHECK(!g_platform);
danakjde3e2a02020-05-12 16:51:20178 g_platform = platform.release();
179 g_platform->Initialize(GetShellDefaultSize());
[email protected]6153b272013-01-25 22:29:23180}
181
arthursonzogni75ede192021-07-06 14:45:46182// static
183void Shell::Shutdown() {
184 if (!g_platform) // Shutdown has already been called.
185 return;
186
187 DevToolsAgentHost::DetachAllClients();
188
189 while (!Shell::windows().empty())
190 Shell::windows().back()->Close();
191
192 delete g_platform;
193 g_platform = nullptr;
194
195 for (auto it = RenderProcessHost::AllHostsIterator(); !it.IsAtEnd();
196 it.Advance()) {
W. James MacLean94cc84962021-09-07 21:51:40197 it.GetCurrentValue()->DisableRefCounts();
arthursonzogni75ede192021-07-06 14:45:46198 }
Lei Zhangebdd085d2022-10-25 17:24:26199 auto& quit_loop = GetMainMessageLoopQuitClosure();
200 if (quit_loop)
201 std::move(quit_loop).Run();
arthursonzogni75ede192021-07-06 14:45:46202
203 // Pump the message loop to allow window teardown tasks to run.
204 base::RunLoop().RunUntilIdle();
205}
206
[email protected]a2904092013-10-15 04:53:59207gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
208 if (!initial_size.IsEmpty())
209 return initial_size;
pdrcab84ee2015-03-13 21:47:04210 return GetShellDefaultSize();
[email protected]a2904092013-10-15 04:53:59211}
212
arthursonzogni75ede192021-07-06 14:45:46213// static
[email protected]bdcf9152012-07-19 17:43:21214Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
[email protected]e99ca5112011-09-26 17:22:54215 const GURL& url,
lukasza04130152016-10-21 20:26:32216 const scoped_refptr<SiteInstance>& site_instance,
[email protected]cdb806722013-01-10 14:18:23217 const gfx::Size& initial_size) {
[email protected]54944cde2012-12-09 09:24:59218 WebContents::CreateParams create_params(browser_context, site_instance);
mark a. foltzef394fce2017-10-21 09:11:02219 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
220 switches::kForcePresentationReceiverForTesting)) {
Johann5a6cf012023-01-17 20:24:13221 create_params.starting_sandbox_flags = kPresentationReceiverSandboxFlags;
mark a. foltzef394fce2017-10-21 09:11:02222 }
erikchenbee5c9622018-04-27 19:30:25223 std::unique_ptr<WebContents> web_contents =
Erik Chenbb8e738e2018-04-28 14:10:43224 WebContents::Create(create_params);
erikchenbee5c9622018-04-27 19:30:25225 Shell* shell =
danakjfc5184932019-09-12 18:08:32226 CreateShell(std::move(web_contents), AdjustWindowSize(initial_size),
Bo Liu300c6052018-06-12 04:46:07227 true /* should_set_delegate */);
danakj7da833932020-06-23 21:49:40228
[email protected]e99ca5112011-09-26 17:22:54229 if (!url.is_empty())
230 shell->LoadURL(url);
[email protected]9fbd3f862011-09-20 23:31:34231 return shell;
232}
233
danakj3dd7a6102020-12-30 19:58:39234void Shell::RenderFrameCreated(RenderFrameHost* frame_host) {
Dave Tapuska327c06c92022-06-13 20:31:51235 if (frame_host == web_contents_->GetPrimaryMainFrame())
danakj3dd7a6102020-12-30 19:58:39236 g_platform->MainFrameCreated(this);
danakj24577b12020-05-13 22:38:18237}
238
[email protected]9fbd3f862011-09-20 23:31:34239void Shell::LoadURL(const GURL& url) {
Alex Moshchuk7e26eca2018-03-03 01:34:29240 LoadURLForFrame(
241 url, std::string(),
242 ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
243 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
[email protected]d2494ff2013-02-20 08:22:37244}
245
Alex Moshchuk7e26eca2018-03-03 01:34:29246void Shell::LoadURLForFrame(const GURL& url,
247 const std::string& frame_name,
248 ui::PageTransition transition_type) {
[email protected]d2494ff2013-02-20 08:22:37249 NavigationController::LoadURLParams params(url);
[email protected]d2494ff2013-02-20 08:22:37250 params.frame_name = frame_name;
Alex Moshchuk7e26eca2018-03-03 01:34:29251 params.transition_type = transition_type;
[email protected]d2494ff2013-02-20 08:22:37252 web_contents_->GetController().LoadURLWithParams(params);
[email protected]9fbd3f862011-09-20 23:31:34253}
254
arthursonzogni75ede192021-07-06 14:45:46255void Shell::LoadDataWithBaseURL(const GURL& url,
256 const std::string& data,
257 const GURL& base_url) {
boliuec93ea92016-02-17 22:23:07258 bool load_as_string = false;
259 LoadDataWithBaseURLInternal(url, data, base_url, load_as_string);
260}
261
Xiaohan Wangbd084422022-01-15 18:47:51262#if BUILDFLAG(IS_ANDROID)
boliuec93ea92016-02-17 22:23:07263void Shell::LoadDataAsStringWithBaseURL(const GURL& url,
264 const std::string& data,
265 const GURL& base_url) {
266 bool load_as_string = true;
267 LoadDataWithBaseURLInternal(url, data, base_url, load_as_string);
268}
269#endif
270
271void Shell::LoadDataWithBaseURLInternal(const GURL& url,
272 const std::string& data,
273 const GURL& base_url,
274 bool load_as_string) {
Xiaohan Wangbd084422022-01-15 18:47:51275#if !BUILDFLAG(IS_ANDROID)
boliuec93ea92016-02-17 22:23:07276 DCHECK(!load_as_string); // Only supported on Android.
277#endif
278
279 NavigationController::LoadURLParams params(GURL::EmptyGURL());
280 const std::string data_url_header = "data:text/html;charset=utf-8,";
281 if (load_as_string) {
282 params.url = GURL(data_url_header);
283 std::string data_url_as_string = data_url_header + data;
Xiaohan Wangbd084422022-01-15 18:47:51284#if BUILDFLAG(IS_ANDROID)
Jongmok Kimc5491082022-10-19 09:17:59285 params.data_url_as_string = base::MakeRefCounted<base::RefCountedString>(
286 std::move(data_url_as_string));
boliuec93ea92016-02-17 22:23:07287#endif
288 } else {
289 params.url = GURL(data_url_header + data);
290 }
291
[email protected]76bdecb2014-04-16 17:58:08292 params.load_type = NavigationController::LOAD_TYPE_DATA;
293 params.base_url_for_data_url = base_url;
294 params.virtual_url_for_data_url = url;
295 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
296 web_contents_->GetController().LoadURLWithParams(params);
[email protected]76bdecb2014-04-16 17:58:08297}
298
[email protected]a2904092013-10-15 04:53:59299void Shell::AddNewContents(WebContents* source,
erikchenbee5c9622018-04-27 19:30:25300 std::unique_ptr<WebContents> new_contents,
Joel Hockey891e88062020-04-30 05:38:44301 const GURL& target_url,
[email protected]a2904092013-10-15 04:53:59302 WindowOpenDisposition disposition,
Brad Triebwasser767c27a2022-08-25 22:56:05303 const blink::mojom::WindowFeatures& window_features,
[email protected]a2904092013-10-15 04:53:59304 bool user_gesture,
305 bool* was_blocked) {
Bo Liu300c6052018-06-12 04:46:07306 CreateShell(
Brad Triebwasser767c27a2022-08-25 22:56:05307 std::move(new_contents), AdjustWindowSize(window_features.bounds.size()),
Bo Liu300c6052018-06-12 04:46:07308 !delay_popup_contents_delegate_for_testing_ /* should_set_delegate */);
[email protected]a2904092013-10-15 04:53:59309}
310
[email protected]9fbd3f862011-09-20 23:31:34311void Shell::GoBackOrForward(int offset) {
[email protected]0b659b32012-03-26 21:29:32312 web_contents_->GetController().GoToOffset(offset);
[email protected]9fbd3f862011-09-20 23:31:34313}
314
315void Shell::Reload() {
toyoshim6142d96f2016-12-19 09:07:25316 web_contents_->GetController().Reload(ReloadType::NORMAL, false);
[email protected]9fbd3f862011-09-20 23:31:34317}
318
toyoshime5aaf6a2016-05-18 08:07:48319void Shell::ReloadBypassingCache() {
toyoshim6142d96f2016-12-19 09:07:25320 web_contents_->GetController().Reload(ReloadType::BYPASSING_CACHE, false);
toyoshime5aaf6a2016-05-18 08:07:48321}
322
[email protected]9fbd3f862011-09-20 23:31:34323void Shell::Stop() {
[email protected]0b659b32012-03-26 21:29:32324 web_contents_->Stop();
[email protected]9fbd3f862011-09-20 23:31:34325}
326
Nate Chapin9aabf5f2021-11-12 00:31:19327void Shell::UpdateNavigationControls(bool should_show_loading_ui) {
[email protected]0b659b32012-03-26 21:29:32328 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
329 int max_index = web_contents_->GetController().GetEntryCount() - 1;
[email protected]9fbd3f862011-09-20 23:31:34330
danakjde3e2a02020-05-12 16:51:20331 g_platform->EnableUIControl(this, ShellPlatformDelegate::BACK_BUTTON,
332 current_index > 0);
333 g_platform->EnableUIControl(this, ShellPlatformDelegate::FORWARD_BUTTON,
334 current_index < max_index);
335 g_platform->EnableUIControl(
336 this, ShellPlatformDelegate::STOP_BUTTON,
Nate Chapin9aabf5f2021-11-12 00:31:19337 should_show_loading_ui && web_contents_->IsLoading());
[email protected]9fbd3f862011-09-20 23:31:34338}
339
[email protected]7c17b6992012-08-09 16:16:30340void Shell::ShowDevTools() {
mohsen6eb57fb2016-07-22 03:14:08341 if (!devtools_frontend_) {
Dave Tapuska5198f0e2021-11-18 15:41:11342 auto* devtools_frontend = ShellDevToolsFrontend::Show(web_contents());
343 devtools_frontend_ = devtools_frontend->GetWeakPtr();
mohsen6eb57fb2016-07-22 03:14:08344 }
[email protected]3142e5d2014-02-07 00:54:46345
mohsen6eb57fb2016-07-22 03:14:08346 devtools_frontend_->Activate();
[email protected]7c17b6992012-08-09 16:16:30347}
348
[email protected]001841c92012-12-11 17:00:13349void Shell::CloseDevTools() {
[email protected]0773e0c2013-01-25 15:57:57350 if (!devtools_frontend_)
[email protected]001841c92012-12-11 17:00:13351 return;
[email protected]0773e0c2013-01-25 15:57:57352 devtools_frontend_->Close();
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28353 devtools_frontend_ = nullptr;
[email protected]001841c92012-12-11 17:00:13354}
355
danakjde3e2a02020-05-12 16:51:20356void Shell::ResizeWebContentForTests(const gfx::Size& content_size) {
357 g_platform->ResizeWebContent(this, content_size);
358}
danakjde3e2a02020-05-12 16:51:20359
[email protected]9fbd3f862011-09-20 23:31:34360gfx::NativeView Shell::GetContentView() {
[email protected]59383c782013-04-17 16:43:27361 if (!web_contents_)
Avi Drissmandad01b0e2023-06-16 22:55:46362 return gfx::NativeView();
[email protected]fc2b46b2014-05-03 16:33:45363 return web_contents_->GetNativeView();
[email protected]9fbd3f862011-09-20 23:31:34364}
365
Xiaohan Wangbd084422022-01-15 18:47:51366#if !BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20367gfx::NativeWindow Shell::window() {
368 return g_platform->GetNativeWindow(this);
369}
370#endif
371
Xiaohan Wangbd084422022-01-15 18:47:51372#if BUILDFLAG(IS_MAC)
danakjde3e2a02020-05-12 16:51:20373void Shell::ActionPerformed(int control) {
374 switch (control) {
375 case IDC_NAV_BACK:
376 GoBackOrForward(-1);
377 break;
378 case IDC_NAV_FORWARD:
379 GoBackOrForward(1);
380 break;
381 case IDC_NAV_RELOAD:
382 Reload();
383 break;
384 case IDC_NAV_STOP:
385 Stop();
386 break;
387 }
388}
389
390void Shell::URLEntered(const std::string& url_string) {
391 if (!url_string.empty()) {
392 GURL url(url_string);
393 if (!url.has_scheme())
394 url = GURL("http://" + url_string);
395 LoadURL(url);
396 }
397}
398#endif
399
alexmos5a98a052016-01-06 00:15:02400WebContents* Shell::OpenURLFromTab(WebContents* source,
401 const OpenURLParams& params) {
lukasza04130152016-10-21 20:26:32402 WebContents* target = nullptr;
403 switch (params.disposition) {
404 case WindowOpenDisposition::CURRENT_TAB:
405 target = source;
406 break;
407
408 // Normally, the difference between NEW_POPUP and NEW_WINDOW is that a popup
409 // should have no toolbar, no status bar, no menu bar, no scrollbars and be
410 // not resizable. For simplicity and to enable new testing scenarios in
Kent Tamura21d1de62018-12-10 04:45:20411 // content shell and web tests, popups don't get special treatment below
lukasza04130152016-10-21 20:26:32412 // (i.e. they will have a toolbar and other things described here).
413 case WindowOpenDisposition::NEW_POPUP:
lukaszabe2f0da2017-04-25 00:43:00414 case WindowOpenDisposition::NEW_WINDOW:
Kent Tamura21d1de62018-12-10 04:45:20415 // content_shell doesn't really support tabs, but some web tests use
lukaszabe2f0da2017-04-25 00:43:00416 // middle click (which translates into kNavigationPolicyNewBackgroundTab),
417 // so we treat the cases below just like a NEW_WINDOW disposition.
418 case WindowOpenDisposition::NEW_BACKGROUND_TAB:
419 case WindowOpenDisposition::NEW_FOREGROUND_TAB: {
lukasza04130152016-10-21 20:26:32420 Shell* new_window =
421 Shell::CreateNewWindow(source->GetBrowserContext(),
422 GURL(), // Don't load anything just yet.
423 params.source_site_instance,
424 gfx::Size()); // Use default size.
425 target = new_window->web_contents();
lukasza04130152016-10-21 20:26:32426 break;
427 }
428
429 // No tabs in content_shell:
430 case WindowOpenDisposition::SINGLETON_TAB:
lukasza04130152016-10-21 20:26:32431 // No incognito mode in content_shell:
432 case WindowOpenDisposition::OFF_THE_RECORD:
Kent Tamura21d1de62018-12-10 04:45:20433 // TODO(lukasza): Investigate if some web tests might need support for
lukasza04130152016-10-21 20:26:32434 // SAVE_TO_DISK disposition. This would probably require that
Gyuyoung Kim26c7bc92020-04-29 00:53:00435 // WebTestControlHost always sets up and cleans up a temporary directory
lukasza04130152016-10-21 20:26:32436 // as the default downloads destinations for the duration of a test.
437 case WindowOpenDisposition::SAVE_TO_DISK:
438 // Ignoring requests with disposition == IGNORE_ACTION...
439 case WindowOpenDisposition::IGNORE_ACTION:
440 default:
441 return nullptr;
442 }
alexmos5a98a052016-01-06 00:15:02443
Lukasz Anforowicz82a5ca92019-10-24 18:45:37444 target->GetController().LoadURLWithParams(
445 NavigationController::LoadURLParams(params));
lukasza04130152016-10-21 20:26:32446 return target;
alexmos5a98a052016-01-06 00:15:02447}
448
[email protected]e3b10d12014-03-28 16:06:09449void Shell::LoadingStateChanged(WebContents* source,
Nate Chapin9aabf5f2021-11-12 00:31:19450 bool should_show_loading_ui) {
451 UpdateNavigationControls(should_show_loading_ui);
danakjde3e2a02020-05-12 16:51:20452 g_platform->SetIsLoading(this, source->IsLoading());
[email protected]e99ca5112011-09-26 17:22:54453}
454
Xiaohan Wangbd084422022-01-15 18:47:51455#if BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20456void Shell::SetOverlayMode(bool use_overlay_mode) {
457 g_platform->SetOverlayMode(this, use_overlay_mode);
458}
459#endif
460
Dave Tapuskaa4189512019-10-15 20:27:34461void Shell::EnterFullscreenModeForTab(
Mike Wasserman4ca09792020-05-29 17:44:43462 RenderFrameHost* requesting_frame,
Dave Tapuskaa4189512019-10-15 20:27:34463 const blink::mojom::FullscreenOptions& options) {
Mike Wasserman4ca09792020-05-29 17:44:43464 ToggleFullscreenModeForTab(WebContents::FromRenderFrameHost(requesting_frame),
465 true);
mlamouri7a78d6fd2015-01-17 13:23:53466}
467
468void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
469 ToggleFullscreenModeForTab(web_contents, false);
470}
471
[email protected]99c014c2012-11-27 12:03:42472void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
473 bool enter_fullscreen) {
Dave Tapuska1efc3012023-02-23 17:27:17474#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
danakjde3e2a02020-05-12 16:51:20475 g_platform->ToggleFullscreenModeForTab(this, web_contents, enter_fullscreen);
[email protected]99c014c2012-11-27 12:03:42476#endif
[email protected]99c014c2012-11-27 12:03:42477 if (is_fullscreen_ != enter_fullscreen) {
478 is_fullscreen_ = enter_fullscreen;
Dave Tapuska327c06c92022-06-13 20:31:51479 web_contents->GetPrimaryMainFrame()
Lucas Furukawa Gadanie7649422021-02-03 03:04:32480 ->GetRenderViewHost()
Fady Samuel0b911822018-04-25 13:22:16481 ->GetWidget()
482 ->SynchronizeVisualProperties();
[email protected]99c014c2012-11-27 12:03:42483 }
484}
485
Lucas Furukawa Gadani4909f3c2019-06-18 22:36:52486bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) {
Dave Tapuska1efc3012023-02-23 17:27:17487#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
danakjde3e2a02020-05-12 16:51:20488 return g_platform->IsFullscreenForTabOrPending(this, web_contents);
[email protected]99c014c2012-11-27 12:03:42489#else
490 return is_fullscreen_;
491#endif
492}
493
Eric Willigers052f0432019-10-04 04:06:57494blink::mojom::DisplayMode Shell::GetDisplayMode(
495 const WebContents* web_contents) {
496 // TODO: should return blink::mojom::DisplayModeFullscreen wherever user puts
Lukasz Anforowicz52b93722018-06-20 16:11:39497 // a browser window into fullscreen (not only in case of renderer-initiated
498 // fullscreen mode): crbug.com/476874.
499 return IsFullscreenForTabOrPending(web_contents)
Eric Willigers052f0432019-10-04 04:06:57500 ? blink::mojom::DisplayMode::kFullscreen
501 : blink::mojom::DisplayMode::kBrowser;
mikhail.pozdnyakovc0e251b2015-04-15 06:51:12502}
503
Javier Fernández García-Boente13150a042022-04-04 21:08:22504#if !BUILDFLAG(IS_ANDROID)
505void Shell::RegisterProtocolHandler(RenderFrameHost* requesting_frame,
506 const std::string& protocol,
507 const GURL& url,
508 bool user_gesture) {
Johann5a6cf012023-01-17 20:24:13509 BrowserContext* context = requesting_frame->GetBrowserContext();
Javier Fernández García-Boente13150a042022-04-04 21:08:22510 if (context->IsOffTheRecord())
511 return;
512
513 custom_handlers::ProtocolHandler handler =
514 custom_handlers::ProtocolHandler::CreateProtocolHandler(
515 protocol, url, GetProtocolHandlerSecurityLevel(requesting_frame));
516
517 // The parameters's normalization process defined in the spec has been already
518 // applied in the WebContentImpl class, so at this point it shouldn't be
519 // possible to create an invalid handler.
520 // https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
521 DCHECK(handler.IsValid());
522
523 custom_handlers::ProtocolHandlerRegistry* registry = custom_handlers::
524 SimpleProtocolHandlerRegistryFactory::GetForBrowserContext(context, true);
525 DCHECK(registry);
526 if (registry->SilentlyHandleRegisterHandlerRequest(handler))
527 return;
528
Javier Fernández García-Boentea2b1f18b2022-04-11 22:05:53529 if (!user_gesture && !windows_.empty()) {
530 // TODO(jfernandez): This is not strictly needed, but we need a way to
531 // inform the observers in browser tests that the request has been
532 // cancelled, to avoid timeouts. Chrome just holds the handler as pending in
533 // the PageContentSettingsDelegate, but we don't have such thing in the
534 // Content Shell.
535 registry->OnDenyRegisterProtocolHandler(handler);
536 return;
537 }
538
Javier Fernández García-Boente13150a042022-04-04 21:08:22539 // FencedFrames can not register to handle any protocols.
540 if (requesting_frame->IsNestedWithinFencedFrame()) {
541 registry->OnIgnoreRegisterProtocolHandler(handler);
542 return;
543 }
544
545 // TODO(jfernandez): Are we interested at all on using the
546 // PermissionRequestManager in the ContentShell ?
Javier Fernández García-Boentec0e70552023-02-03 09:41:13547 if (registry->registration_mode() ==
548 custom_handlers::RphRegistrationMode::kAutoAccept) {
549 registry->OnAcceptRegisterProtocolHandler(handler);
550 }
Javier Fernández García-Boente13150a042022-04-04 21:08:22551}
552#endif
553
[email protected]f78439002012-11-28 14:45:59554void Shell::RequestToLockMouse(WebContents* web_contents,
555 bool user_gesture,
556 bool last_unlocked_by_target) {
Dave Tapuskab4998782020-10-08 17:22:47557 // Give the platform a chance to handle the lock request, if it doesn't
558 // indicate it handled it, allow the request.
559 if (!g_platform->HandleRequestToLockMouse(this, web_contents, user_gesture,
560 last_unlocked_by_target)) {
561 web_contents->GotResponseToLockMouseRequest(
562 blink::mojom::PointerLockResult::kSuccess);
563 }
[email protected]f78439002012-11-28 14:45:59564}
565
danakjde3e2a02020-05-12 16:51:20566void Shell::Close() {
567 // Shell is "self-owned" and destroys itself. The ShellPlatformDelegate
568 // has the chance to co-opt this and do its own destruction.
569 if (!g_platform->DestroyShell(this))
570 delete this;
571}
572
[email protected]9e00e6352012-07-30 17:05:18573void Shell::CloseContents(WebContents* source) {
574 Close();
575}
576
Lucas Furukawa Gadani4909f3c2019-06-18 22:36:52577bool Shell::CanOverscrollContent() {
[email protected]067310262012-11-22 14:30:41578#if defined(USE_AURA)
579 return true;
580#else
581 return false;
582#endif
583}
584
Mugdha Lakhani5f8de7cc2020-03-10 20:43:36585void Shell::NavigationStateChanged(WebContents* source,
586 InvalidateTypes changed_flags) {
587 if (changed_flags & INVALIDATE_TYPE_URL)
danakjde3e2a02020-05-12 16:51:20588 g_platform->SetAddressBarURL(this, source->GetVisibleURL());
[email protected]e99ca5112011-09-26 17:22:54589}
590
mathiash72a5e462014-11-19 08:18:50591JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
592 WebContents* source) {
danakj8de3b7492020-07-02 22:41:42593 if (!dialog_manager_)
594 dialog_manager_ = g_platform->CreateJavaScriptDialogManager(this);
595 if (!dialog_manager_)
596 dialog_manager_ = std::make_unique<ShellJavaScriptDialogManager>();
[email protected]71a88bb2013-02-01 22:05:15597 return dialog_manager_.get();
[email protected]f2210022012-03-29 00:36:08598}
599
Xiaohan Wangbd084422022-01-15 18:47:51600#if BUILDFLAG(IS_MAC)
Johann5a6cf012023-01-17 20:24:13601void Shell::PrimaryPageChanged(Page& page) {
Julie Jeongeun Kimc37853f2022-12-16 11:00:32602 g_platform->DidNavigatePrimaryMainFramePostCommit(
Johann5a6cf012023-01-17 20:24:13603 this, WebContents::FromRenderFrameHost(&page.GetMainDocument()));
Xianzhu Wang0f021a82020-07-03 01:29:47604}
605
danakjde3e2a02020-05-12 16:51:20606bool Shell::HandleKeyboardEvent(WebContents* source,
607 const NativeWebKeyboardEvent& event) {
608 return g_platform->HandleKeyboardEvent(this, source, event);
609}
610#endif
611
avia90ae4e2016-11-11 20:49:33612bool Shell::DidAddMessageToConsole(WebContents* source,
Lowell Manners1de5242e2019-04-25 10:18:46613 blink::mojom::ConsoleMessageLevel log_level,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58614 const std::u16string& message,
avia90ae4e2016-11-11 20:49:33615 int32_t line_no,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58616 const std::u16string& source_id) {
Kent Tamuracd3ebc42018-05-16 06:44:22617 return switches::IsRunWebTestsSwitchPresent();
[email protected]efb5f572012-01-29 10:57:33618}
619
Lucas Furukawa Gadani06548fb2019-01-15 05:01:25620void Shell::PortalWebContentsCreated(WebContents* portal_web_contents) {
danakj8de3b7492020-07-02 22:41:42621 g_platform->DidCreateOrAttachWebContents(this, portal_web_contents);
Lucas Furukawa Gadani06548fb2019-01-15 05:01:25622}
623
Lukasz Anforowicz52b93722018-06-20 16:11:39624void Shell::RendererUnresponsive(
625 WebContents* source,
626 RenderWidgetHost* render_widget_host,
627 base::RepeatingClosure hang_monitor_restarter) {
danakj245441f2020-07-03 15:18:41628 LOG(WARNING) << "renderer unresponsive";
[email protected]5bf68f22012-08-31 07:38:10629}
630
[email protected]233567d2013-02-27 20:22:02631void Shell::ActivateContents(WebContents* contents) {
Xiaohan Wangbd084422022-01-15 18:47:51632#if !BUILDFLAG(IS_MAC)
danakjd4b48df52020-07-02 18:16:48633 // TODO(danakj): Move this to ShellPlatformDelegate.
danakj674bf1c02020-05-01 18:37:51634 contents->Focus();
635#else
636 // Mac headless mode is quite different than other platforms. Normally
637 // focusing the WebContents would cause the OS to focus the window. Because
638 // headless mac doesn't actually have system windows, we can't go down the
639 // normal path and have to fake it out in the browser process.
danakjde3e2a02020-05-12 16:51:20640 g_platform->ActivateContents(this, contents);
danakj674bf1c02020-05-01 18:37:51641#endif
[email protected]233567d2013-02-27 20:22:02642}
643
Julie Jeongeun Kimec508272023-03-17 04:17:12644void Shell::RunFileChooser(RenderFrameHost* render_frame_host,
645 scoped_refptr<FileSelectListener> listener,
646 const blink::mojom::FileChooserParams& params) {
647 g_platform->RunFileChooser(render_frame_host, std::move(listener), params);
648}
649
Dave Tapuskadfff7382021-04-23 19:46:41650bool Shell::IsBackForwardCacheSupported() {
651 return true;
652}
653
Johanna0b3e9b2023-01-19 23:23:35654PreloadingEligibility Shell::IsPrerender2Supported(WebContents& web_contents) {
655 return PreloadingEligibility::kEligible;
Lingqi Chi8159aec2021-06-15 01:46:03656}
657
Kevin McNee7422bc42020-02-20 18:49:55658std::unique_ptr<WebContents> Shell::ActivatePortalWebContents(
659 WebContents* predecessor_contents,
660 std::unique_ptr<WebContents> portal_contents) {
661 DCHECK_EQ(predecessor_contents, web_contents_.get());
662 portal_contents->SetDelegate(this);
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33663 web_contents_->SetDelegate(nullptr);
Kevin McNee7422bc42020-02-20 18:49:55664 std::swap(web_contents_, portal_contents);
danakjde3e2a02020-05-12 16:51:20665 g_platform->SetContents(this);
666 g_platform->SetAddressBarURL(this, web_contents_->GetVisibleURL());
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33667 LoadingStateChanged(web_contents_.get(), true);
Kevin McNee7422bc42020-02-20 18:49:55668 return portal_contents;
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33669}
670
Adithya Srinivasanb7204c82020-08-17 14:26:33671namespace {
672class PendingCallback : public base::RefCounted<PendingCallback> {
673 public:
674 explicit PendingCallback(base::OnceCallback<void()> cb)
675 : callback_(std::move(cb)) {}
676
677 private:
678 friend class base::RefCounted<PendingCallback>;
679 ~PendingCallback() { std::move(callback_).Run(); }
680 base::OnceCallback<void()> callback_;
681};
682} // namespace
683
684void Shell::UpdateInspectedWebContentsIfNecessary(
Johann5a6cf012023-01-17 20:24:13685 WebContents* old_contents,
686 WebContents* new_contents,
Adithya Srinivasanb7204c82020-08-17 14:26:33687 base::OnceCallback<void()> callback) {
688 scoped_refptr<PendingCallback> pending_callback =
689 base::MakeRefCounted<PendingCallback>(std::move(callback));
690 for (auto* shell_devtools_bindings :
691 ShellDevToolsBindings::GetInstancesForWebContents(old_contents)) {
692 shell_devtools_bindings->UpdateInspectedWebContents(
Paul Semel4c1e3e82022-10-24 09:20:54693 new_contents, base::DoNothingWithBoundArgs(pending_callback));
Adithya Srinivasanb7204c82020-08-17 14:26:33694 }
695}
696
Lukasz Anforowicz82a5ca92019-10-24 18:45:37697bool Shell::ShouldAllowRunningInsecureContent(WebContents* web_contents,
698 bool allowed_per_prefs,
699 const url::Origin& origin,
700 const GURL& resource_url) {
danakj8de3b7492020-07-02 22:41:42701 if (allowed_per_prefs)
702 return true;
carloskd9d97942017-02-16 08:58:09703
danakj8de3b7492020-07-02 22:41:42704 return g_platform->ShouldAllowRunningInsecureContent(this);
carloskd9d97942017-02-16 08:58:09705}
706
François Beaufort1388f2892022-01-29 08:22:47707PictureInPictureResult Shell::EnterPictureInPicture(WebContents* web_contents) {
Becca Hughes112832e2019-06-11 17:19:02708 // During tests, returning success to pretend the window was created and allow
709 // tests to run accordingly.
710 if (!switches::IsRunWebTestsSwitchPresent())
711 return PictureInPictureResult::kNotSupported;
Becca Hughes112832e2019-06-11 17:19:02712 return PictureInPictureResult::kSuccess;
Mounir Lamouri11e9ef432018-05-22 03:10:16713}
714
Bo Liu300c6052018-06-12 04:46:07715bool Shell::ShouldResumeRequestsForCreatedWindow() {
716 return !delay_popup_contents_delegate_for_testing_;
717}
718
danakjee2390a82020-06-10 16:53:37719void Shell::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
720 DCHECK(source == web_contents()); // There's only one WebContents per Shell.
721
722 if (switches::IsRunWebTestsSwitchPresent()) {
723 // Note that chrome drops these requests on normal windows.
724 // TODO(danakj): The position is dropped here but we use the size. Web tests
725 // can't move the window in headless mode anyways, but maybe we should be
726 // letting them pretend?
727 g_platform->ResizeWebContent(this, bounds.size());
728 }
729}
730
pdrcab84ee2015-03-13 21:47:04731gfx::Size Shell::GetShellDefaultSize() {
danakj6c16fe92020-09-18 23:51:32732 static gfx::Size default_shell_size; // Only go through this method once.
733
pdrcab84ee2015-03-13 21:47:04734 if (!default_shell_size.IsEmpty())
735 return default_shell_size;
danakj6c16fe92020-09-18 23:51:32736
pdrcab84ee2015-03-13 21:47:04737 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
738 if (command_line->HasSwitch(switches::kContentShellHostWindowSize)) {
739 const std::string size_str = command_line->GetSwitchValueASCII(
arthursonzogni75ede192021-07-06 14:45:46740 switches::kContentShellHostWindowSize);
pdrcab84ee2015-03-13 21:47:04741 int width, height;
danakj6c16fe92020-09-18 23:51:32742 if (sscanf(size_str.c_str(), "%dx%d", &width, &height) == 2) {
743 default_shell_size = gfx::Size(width, height);
744 } else {
745 LOG(ERROR) << "Invalid size \"" << size_str << "\" given to --"
746 << switches::kContentShellHostWindowSize;
747 }
748 }
749
750 if (default_shell_size.IsEmpty()) {
arthursonzogni75ede192021-07-06 14:45:46751 default_shell_size =
752 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
pdrcab84ee2015-03-13 21:47:04753 }
danakj6c16fe92020-09-18 23:51:32754
pdrcab84ee2015-03-13 21:47:04755 return default_shell_size;
756}
757
Xiaohan Wangbd084422022-01-15 18:47:51758#if BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20759void Shell::LoadProgressChanged(double progress) {
760 g_platform->LoadProgressChanged(this, progress);
761}
762#endif
763
Avi Drissman93002212017-09-27 03:20:52764void Shell::TitleWasSet(NavigationEntry* entry) {
[email protected]1ef02d242013-10-07 16:18:53765 if (entry)
danakjde3e2a02020-05-12 16:51:20766 g_platform->SetTitle(this, entry->GetTitle());
[email protected]aecc085b2012-06-01 18:15:53767}
768
[email protected]9fbd3f862011-09-20 23:31:34769} // namespace content