blob: 379c87f573b53611fc4fb633958df0cf33d86e08 [file] [log] [blame]
[email protected]de7d61ff2013-08-20 11:30:411// Copyright 2013 The Chromium Authors. All rights reserved.
[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"
skyostil95082a62015-06-05 19:53:0715#include "base/location.h"
Wez9a58a152018-06-07 18:59:3316#include "base/no_destructor.h"
fdoray896bea12016-06-10 15:52:0117#include "base/run_loop.h"
[email protected]21aa99682013-06-11 07:17:0118#include "base/strings/string_number_conversions.h"
19#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0020#include "base/strings/utf_string_conversions.h"
Patrick Monette643cdf62021-10-15 19:13:4221#include "base/task/single_thread_task_runner.h"
gab30f26df2016-05-11 19:37:5522#include "base/threading/thread_task_runner_handle.h"
avi66a07722015-12-25 23:38:1223#include "build/build_config.h"
Javier Fernández García-Boente13150a042022-04-04 21:08:2224#include "components/custom_handlers/protocol_handler.h"
25#include "components/custom_handlers/protocol_handler_registry.h"
26#include "components/custom_handlers/simple_protocol_handler_registry_factory.h"
27#include "content/public/browser/browser_context.h"
[email protected]b50452f2014-08-18 12:31:4428#include "content/public/browser/devtools_agent_host.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"
[email protected]9fbd3f862011-09-20 23:31:3447
[email protected]9fbd3f862011-09-20 23:31:3448namespace content {
49
arthursonzogni75ede192021-07-06 14:45:4650namespace {
Wezcbf4a042018-06-13 16:29:1251// Null until/unless the default main message loop is running.
52base::NoDestructor<base::OnceClosure> g_quit_main_message_loop;
Wez9a58a152018-06-07 18:59:3353
pdrcab84ee2015-03-13 21:47:0454const int kDefaultTestWindowWidthDip = 800;
55const int kDefaultTestWindowHeightDip = 600;
[email protected]1e57cab2013-05-28 04:26:1156
arthursonzogni75ede192021-07-06 14:45:4657// Owning pointer. We can not use unique_ptr as a global. That introduces a
58// static constructor/destructor.
59// Acquired in Shell::Init(), released in Shell::Shutdown().
60ShellPlatformDelegate* g_platform;
61} // namespace
62
[email protected]e99ca5112011-09-26 17:22:5463std::vector<Shell*> Shell::windows_;
danakja9fe91c2019-05-01 19:02:2964base::OnceCallback<void(Shell*)> Shell::shell_created_callback_;
[email protected]9fbd3f862011-09-20 23:31:3465
Bo Liu300c6052018-06-12 04:46:0766Shell::Shell(std::unique_ptr<WebContents> web_contents,
67 bool should_set_delegate)
erikchenbee5c9622018-04-27 19:30:2568 : WebContentsObserver(web_contents.get()),
danakjde3e2a02020-05-12 16:51:2069 web_contents_(std::move(web_contents)) {
Bo Liu300c6052018-06-12 04:46:0770 if (should_set_delegate)
71 web_contents_->SetDelegate(this);
arthursonzognifdd49912017-08-31 08:55:2672
danakjd4b48df52020-07-02 18:16:4873 if (!switches::IsRunWebTestsSwitchPresent()) {
Xianzhu Wang6be66b012020-05-06 17:17:2574 UpdateFontRendererPreferencesFromSystemSettings(
75 web_contents_->GetMutableRendererPrefs());
Francois Doraye6161152018-03-27 22:05:3776 }
Pavel Feldmanc7cd063c2017-10-06 20:04:2877
[email protected]9e00e6352012-07-30 17:05:1878 windows_.push_back(this);
79
danakja9fe91c2019-05-01 19:02:2980 if (shell_created_callback_)
81 std::move(shell_created_callback_).Run(this);
[email protected]9fbd3f862011-09-20 23:31:3482}
83
84Shell::~Shell() {
danakjde3e2a02020-05-12 16:51:2085 g_platform->CleanUp(this);
[email protected]e99ca5112011-09-26 17:22:5486
87 for (size_t i = 0; i < windows_.size(); ++i) {
88 if (windows_[i] == this) {
89 windows_.erase(windows_.begin() + i);
90 break;
91 }
92 }
[email protected]11a65b692012-03-30 11:29:1693
Sergey Ulanovf0875d12019-01-03 20:33:2394 web_contents_->SetDelegate(nullptr);
95 web_contents_.reset();
Arthur Sonzogni9e72df3f2021-07-02 14:32:1796
arthursonzogni75ede192021-07-06 14:45:4697 if (windows().empty())
98 g_platform->DidCloseLastWindow();
[email protected]9fbd3f862011-09-20 23:31:3499}
100
erikchenbee5c9622018-04-27 19:30:25101Shell* Shell::CreateShell(std::unique_ptr<WebContents> web_contents,
Bo Liu300c6052018-06-12 04:46:07102 const gfx::Size& initial_size,
103 bool should_set_delegate) {
erikchenbee5c9622018-04-27 19:30:25104 WebContents* raw_web_contents = web_contents.get();
Bo Liu300c6052018-06-12 04:46:07105 Shell* shell = new Shell(std::move(web_contents), should_set_delegate);
danakjde3e2a02020-05-12 16:51:20106 g_platform->CreatePlatformWindow(shell, initial_size);
[email protected]1596efb2013-01-17 22:13:01107
creisb6561df2016-02-11 20:20:54108 // Note: Do not make RenderFrameHost or RenderViewHost specific state changes
109 // here, because they will be forgotten after a cross-process navigation. Use
110 // RenderFrameCreated or RenderViewCreated instead.
Kent Tamuracd3ebc42018-05-16 06:44:22111 if (switches::IsRunWebTestsSwitchPresent()) {
erikchenbee5c9622018-04-27 19:30:25112 raw_web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
Bruce Long1e3e1f542019-10-16 17:56:28113 raw_web_contents->SyncRendererPrefs();
[email protected]1596efb2013-01-17 22:13:01114 }
115
lukasza381b0492016-03-10 16:48:43116 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
guoweis4ee48592015-12-02 06:37:07117 if (command_line->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) {
erikchenbee5c9622018-04-27 19:30:25118 raw_web_contents->GetMutableRendererPrefs()->webrtc_ip_handling_policy =
guoweis4ee48592015-12-02 06:37:07119 command_line->GetSwitchValueASCII(
120 switches::kForceWebRtcIPHandlingPolicy);
guoweis8efb6d892015-10-12 18:26:17121 }
guoweis8efb6d892015-10-12 18:26:17122
danakj8de3b7492020-07-02 22:41:42123 g_platform->SetContents(shell);
124 g_platform->DidCreateOrAttachWebContents(shell, raw_web_contents);
danakj3dd7a6102020-12-30 19:58:39125 // If the RenderFrame was created during WebContents construction (as happens
126 // for windows opened from the renderer) then the Shell won't hear about the
127 // main frame being created as a WebContentsObservers. This gives the delegate
128 // a chance to act on the main frame accordingly.
129 if (raw_web_contents->GetMainFrame()->IsRenderFrameCreated())
130 g_platform->MainFrameCreated(shell);
danakj7da833932020-06-23 21:49:40131
[email protected]3fd84032012-01-12 18:20:17132 return shell;
133}
134
arthursonzogni75ede192021-07-06 14:45:46135// static
Wezcbf4a042018-06-13 16:29:12136void Shell::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
137 *g_quit_main_message_loop = std::move(quit_closure);
138}
139
arthursonzogni75ede192021-07-06 14:45:46140// static
Wez7d3eb012018-06-20 22:51:28141void Shell::QuitMainMessageLoopForTesting() {
Wezc93f15a92020-02-25 21:57:44142 if (*g_quit_main_message_loop)
143 std::move(*g_quit_main_message_loop).Run();
Wez7d3eb012018-06-20 22:51:28144}
145
arthursonzogni75ede192021-07-06 14:45:46146// static
[email protected]9e00e6352012-07-30 17:05:18147void Shell::SetShellCreatedCallback(
danakja9fe91c2019-05-01 19:02:29148 base::OnceCallback<void(Shell*)> shell_created_callback) {
149 DCHECK(!shell_created_callback_);
Tommy Nyquist4b749d02018-03-20 21:46:29150 shell_created_callback_ = std::move(shell_created_callback);
[email protected]9e00e6352012-07-30 17:05:18151}
152
danakjde3e2a02020-05-12 16:51:20153// static
154bool Shell::ShouldHideToolbar() {
155 return base::CommandLine::ForCurrentProcess()->HasSwitch(
156 switches::kContentShellHideToolbar);
157}
158
arthursonzogni75ede192021-07-06 14:45:46159// static
David Benjaminf62c6662019-03-21 20:25:04160Shell* Shell::FromWebContents(WebContents* web_contents) {
161 for (Shell* window : windows_) {
162 if (window->web_contents() && window->web_contents() == web_contents) {
163 return window;
[email protected]74830f02012-01-30 22:27:04164 }
165 }
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28166 return nullptr;
[email protected]74830f02012-01-30 22:27:04167}
168
arthursonzogni75ede192021-07-06 14:45:46169// static
danakjde3e2a02020-05-12 16:51:20170void Shell::Initialize(std::unique_ptr<ShellPlatformDelegate> platform) {
arthursonzogni75ede192021-07-06 14:45:46171 DCHECK(!g_platform);
danakjde3e2a02020-05-12 16:51:20172 g_platform = platform.release();
173 g_platform->Initialize(GetShellDefaultSize());
[email protected]6153b272013-01-25 22:29:23174}
175
arthursonzogni75ede192021-07-06 14:45:46176// static
177void Shell::Shutdown() {
178 if (!g_platform) // Shutdown has already been called.
179 return;
180
181 DevToolsAgentHost::DetachAllClients();
182
183 while (!Shell::windows().empty())
184 Shell::windows().back()->Close();
185
186 delete g_platform;
187 g_platform = nullptr;
188
189 for (auto it = RenderProcessHost::AllHostsIterator(); !it.IsAtEnd();
190 it.Advance()) {
W. James MacLean94cc84962021-09-07 21:51:40191 it.GetCurrentValue()->DisableRefCounts();
arthursonzogni75ede192021-07-06 14:45:46192 }
193 if (*g_quit_main_message_loop)
194 std::move(*g_quit_main_message_loop).Run();
195
196 // Pump the message loop to allow window teardown tasks to run.
197 base::RunLoop().RunUntilIdle();
198}
199
[email protected]a2904092013-10-15 04:53:59200gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
201 if (!initial_size.IsEmpty())
202 return initial_size;
pdrcab84ee2015-03-13 21:47:04203 return GetShellDefaultSize();
[email protected]a2904092013-10-15 04:53:59204}
205
arthursonzogni75ede192021-07-06 14:45:46206// static
[email protected]bdcf9152012-07-19 17:43:21207Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
[email protected]e99ca5112011-09-26 17:22:54208 const GURL& url,
lukasza04130152016-10-21 20:26:32209 const scoped_refptr<SiteInstance>& site_instance,
[email protected]cdb806722013-01-10 14:18:23210 const gfx::Size& initial_size) {
[email protected]54944cde2012-12-09 09:24:59211 WebContents::CreateParams create_params(browser_context, site_instance);
mark a. foltzef394fce2017-10-21 09:11:02212 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
213 switches::kForcePresentationReceiverForTesting)) {
214 create_params.starting_sandbox_flags =
arthursonzognib93a4472020-04-10 07:38:00215 content::kPresentationReceiverSandboxFlags;
mark a. foltzef394fce2017-10-21 09:11:02216 }
erikchenbee5c9622018-04-27 19:30:25217 std::unique_ptr<WebContents> web_contents =
Erik Chenbb8e738e2018-04-28 14:10:43218 WebContents::Create(create_params);
erikchenbee5c9622018-04-27 19:30:25219 Shell* shell =
danakjfc5184932019-09-12 18:08:32220 CreateShell(std::move(web_contents), AdjustWindowSize(initial_size),
Bo Liu300c6052018-06-12 04:46:07221 true /* should_set_delegate */);
danakj7da833932020-06-23 21:49:40222
[email protected]e99ca5112011-09-26 17:22:54223 if (!url.is_empty())
224 shell->LoadURL(url);
[email protected]9fbd3f862011-09-20 23:31:34225 return shell;
226}
227
danakj3dd7a6102020-12-30 19:58:39228void Shell::RenderFrameCreated(RenderFrameHost* frame_host) {
229 if (frame_host == web_contents_->GetMainFrame())
230 g_platform->MainFrameCreated(this);
danakj24577b12020-05-13 22:38:18231}
232
[email protected]9fbd3f862011-09-20 23:31:34233void Shell::LoadURL(const GURL& url) {
Alex Moshchuk7e26eca2018-03-03 01:34:29234 LoadURLForFrame(
235 url, std::string(),
236 ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
237 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
[email protected]d2494ff2013-02-20 08:22:37238}
239
Alex Moshchuk7e26eca2018-03-03 01:34:29240void Shell::LoadURLForFrame(const GURL& url,
241 const std::string& frame_name,
242 ui::PageTransition transition_type) {
[email protected]d2494ff2013-02-20 08:22:37243 NavigationController::LoadURLParams params(url);
[email protected]d2494ff2013-02-20 08:22:37244 params.frame_name = frame_name;
Alex Moshchuk7e26eca2018-03-03 01:34:29245 params.transition_type = transition_type;
[email protected]d2494ff2013-02-20 08:22:37246 web_contents_->GetController().LoadURLWithParams(params);
[email protected]9fbd3f862011-09-20 23:31:34247}
248
arthursonzogni75ede192021-07-06 14:45:46249void Shell::LoadDataWithBaseURL(const GURL& url,
250 const std::string& data,
251 const GURL& base_url) {
boliuec93ea92016-02-17 22:23:07252 bool load_as_string = false;
253 LoadDataWithBaseURLInternal(url, data, base_url, load_as_string);
254}
255
Xiaohan Wangbd084422022-01-15 18:47:51256#if BUILDFLAG(IS_ANDROID)
boliuec93ea92016-02-17 22:23:07257void Shell::LoadDataAsStringWithBaseURL(const GURL& url,
258 const std::string& data,
259 const GURL& base_url) {
260 bool load_as_string = true;
261 LoadDataWithBaseURLInternal(url, data, base_url, load_as_string);
262}
263#endif
264
265void Shell::LoadDataWithBaseURLInternal(const GURL& url,
266 const std::string& data,
267 const GURL& base_url,
268 bool load_as_string) {
Xiaohan Wangbd084422022-01-15 18:47:51269#if !BUILDFLAG(IS_ANDROID)
boliuec93ea92016-02-17 22:23:07270 DCHECK(!load_as_string); // Only supported on Android.
271#endif
272
273 NavigationController::LoadURLParams params(GURL::EmptyGURL());
274 const std::string data_url_header = "data:text/html;charset=utf-8,";
275 if (load_as_string) {
276 params.url = GURL(data_url_header);
277 std::string data_url_as_string = data_url_header + data;
Xiaohan Wangbd084422022-01-15 18:47:51278#if BUILDFLAG(IS_ANDROID)
boliuec93ea92016-02-17 22:23:07279 params.data_url_as_string =
280 base::RefCountedString::TakeString(&data_url_as_string);
281#endif
282 } else {
283 params.url = GURL(data_url_header + data);
284 }
285
[email protected]76bdecb2014-04-16 17:58:08286 params.load_type = NavigationController::LOAD_TYPE_DATA;
287 params.base_url_for_data_url = base_url;
288 params.virtual_url_for_data_url = url;
289 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
290 web_contents_->GetController().LoadURLWithParams(params);
[email protected]76bdecb2014-04-16 17:58:08291}
292
[email protected]a2904092013-10-15 04:53:59293void Shell::AddNewContents(WebContents* source,
erikchenbee5c9622018-04-27 19:30:25294 std::unique_ptr<WebContents> new_contents,
Joel Hockey891e88062020-04-30 05:38:44295 const GURL& target_url,
[email protected]a2904092013-10-15 04:53:59296 WindowOpenDisposition disposition,
bokan107a47f2015-02-03 23:23:39297 const gfx::Rect& initial_rect,
[email protected]a2904092013-10-15 04:53:59298 bool user_gesture,
299 bool* was_blocked) {
Bo Liu300c6052018-06-12 04:46:07300 CreateShell(
301 std::move(new_contents), AdjustWindowSize(initial_rect.size()),
302 !delay_popup_contents_delegate_for_testing_ /* should_set_delegate */);
[email protected]a2904092013-10-15 04:53:59303}
304
[email protected]9fbd3f862011-09-20 23:31:34305void Shell::GoBackOrForward(int offset) {
[email protected]0b659b32012-03-26 21:29:32306 web_contents_->GetController().GoToOffset(offset);
[email protected]9fbd3f862011-09-20 23:31:34307}
308
309void Shell::Reload() {
toyoshim6142d96f2016-12-19 09:07:25310 web_contents_->GetController().Reload(ReloadType::NORMAL, false);
[email protected]9fbd3f862011-09-20 23:31:34311}
312
toyoshime5aaf6a2016-05-18 08:07:48313void Shell::ReloadBypassingCache() {
toyoshim6142d96f2016-12-19 09:07:25314 web_contents_->GetController().Reload(ReloadType::BYPASSING_CACHE, false);
toyoshime5aaf6a2016-05-18 08:07:48315}
316
[email protected]9fbd3f862011-09-20 23:31:34317void Shell::Stop() {
[email protected]0b659b32012-03-26 21:29:32318 web_contents_->Stop();
[email protected]9fbd3f862011-09-20 23:31:34319}
320
Nate Chapin9aabf5f2021-11-12 00:31:19321void Shell::UpdateNavigationControls(bool should_show_loading_ui) {
[email protected]0b659b32012-03-26 21:29:32322 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
323 int max_index = web_contents_->GetController().GetEntryCount() - 1;
[email protected]9fbd3f862011-09-20 23:31:34324
danakjde3e2a02020-05-12 16:51:20325 g_platform->EnableUIControl(this, ShellPlatformDelegate::BACK_BUTTON,
326 current_index > 0);
327 g_platform->EnableUIControl(this, ShellPlatformDelegate::FORWARD_BUTTON,
328 current_index < max_index);
329 g_platform->EnableUIControl(
330 this, ShellPlatformDelegate::STOP_BUTTON,
Nate Chapin9aabf5f2021-11-12 00:31:19331 should_show_loading_ui && web_contents_->IsLoading());
[email protected]9fbd3f862011-09-20 23:31:34332}
333
[email protected]7c17b6992012-08-09 16:16:30334void Shell::ShowDevTools() {
mohsen6eb57fb2016-07-22 03:14:08335 if (!devtools_frontend_) {
Dave Tapuska5198f0e2021-11-18 15:41:11336 auto* devtools_frontend = ShellDevToolsFrontend::Show(web_contents());
337 devtools_frontend_ = devtools_frontend->GetWeakPtr();
mohsen6eb57fb2016-07-22 03:14:08338 }
[email protected]3142e5d2014-02-07 00:54:46339
mohsen6eb57fb2016-07-22 03:14:08340 devtools_frontend_->Activate();
[email protected]7c17b6992012-08-09 16:16:30341}
342
[email protected]001841c92012-12-11 17:00:13343void Shell::CloseDevTools() {
[email protected]0773e0c2013-01-25 15:57:57344 if (!devtools_frontend_)
[email protected]001841c92012-12-11 17:00:13345 return;
[email protected]0773e0c2013-01-25 15:57:57346 devtools_frontend_->Close();
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28347 devtools_frontend_ = nullptr;
[email protected]001841c92012-12-11 17:00:13348}
349
danakjde3e2a02020-05-12 16:51:20350void Shell::ResizeWebContentForTests(const gfx::Size& content_size) {
351 g_platform->ResizeWebContent(this, content_size);
352}
danakjde3e2a02020-05-12 16:51:20353
[email protected]9fbd3f862011-09-20 23:31:34354gfx::NativeView Shell::GetContentView() {
[email protected]59383c782013-04-17 16:43:27355 if (!web_contents_)
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28356 return nullptr;
[email protected]fc2b46b2014-05-03 16:33:45357 return web_contents_->GetNativeView();
[email protected]9fbd3f862011-09-20 23:31:34358}
359
Xiaohan Wangbd084422022-01-15 18:47:51360#if !BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20361gfx::NativeWindow Shell::window() {
362 return g_platform->GetNativeWindow(this);
363}
364#endif
365
Xiaohan Wangbd084422022-01-15 18:47:51366#if BUILDFLAG(IS_MAC)
danakjde3e2a02020-05-12 16:51:20367void Shell::ActionPerformed(int control) {
368 switch (control) {
369 case IDC_NAV_BACK:
370 GoBackOrForward(-1);
371 break;
372 case IDC_NAV_FORWARD:
373 GoBackOrForward(1);
374 break;
375 case IDC_NAV_RELOAD:
376 Reload();
377 break;
378 case IDC_NAV_STOP:
379 Stop();
380 break;
381 }
382}
383
384void Shell::URLEntered(const std::string& url_string) {
385 if (!url_string.empty()) {
386 GURL url(url_string);
387 if (!url.has_scheme())
388 url = GURL("http://" + url_string);
389 LoadURL(url);
390 }
391}
392#endif
393
alexmos5a98a052016-01-06 00:15:02394WebContents* Shell::OpenURLFromTab(WebContents* source,
395 const OpenURLParams& params) {
lukasza04130152016-10-21 20:26:32396 WebContents* target = nullptr;
397 switch (params.disposition) {
398 case WindowOpenDisposition::CURRENT_TAB:
399 target = source;
400 break;
401
402 // Normally, the difference between NEW_POPUP and NEW_WINDOW is that a popup
403 // should have no toolbar, no status bar, no menu bar, no scrollbars and be
404 // not resizable. For simplicity and to enable new testing scenarios in
Kent Tamura21d1de62018-12-10 04:45:20405 // content shell and web tests, popups don't get special treatment below
lukasza04130152016-10-21 20:26:32406 // (i.e. they will have a toolbar and other things described here).
407 case WindowOpenDisposition::NEW_POPUP:
lukaszabe2f0da2017-04-25 00:43:00408 case WindowOpenDisposition::NEW_WINDOW:
Kent Tamura21d1de62018-12-10 04:45:20409 // content_shell doesn't really support tabs, but some web tests use
lukaszabe2f0da2017-04-25 00:43:00410 // middle click (which translates into kNavigationPolicyNewBackgroundTab),
411 // so we treat the cases below just like a NEW_WINDOW disposition.
412 case WindowOpenDisposition::NEW_BACKGROUND_TAB:
413 case WindowOpenDisposition::NEW_FOREGROUND_TAB: {
lukasza04130152016-10-21 20:26:32414 Shell* new_window =
415 Shell::CreateNewWindow(source->GetBrowserContext(),
416 GURL(), // Don't load anything just yet.
417 params.source_site_instance,
418 gfx::Size()); // Use default size.
419 target = new_window->web_contents();
lukasza04130152016-10-21 20:26:32420 break;
421 }
422
423 // No tabs in content_shell:
424 case WindowOpenDisposition::SINGLETON_TAB:
lukasza04130152016-10-21 20:26:32425 // No incognito mode in content_shell:
426 case WindowOpenDisposition::OFF_THE_RECORD:
Kent Tamura21d1de62018-12-10 04:45:20427 // TODO(lukasza): Investigate if some web tests might need support for
lukasza04130152016-10-21 20:26:32428 // SAVE_TO_DISK disposition. This would probably require that
Gyuyoung Kim26c7bc92020-04-29 00:53:00429 // WebTestControlHost always sets up and cleans up a temporary directory
lukasza04130152016-10-21 20:26:32430 // as the default downloads destinations for the duration of a test.
431 case WindowOpenDisposition::SAVE_TO_DISK:
432 // Ignoring requests with disposition == IGNORE_ACTION...
433 case WindowOpenDisposition::IGNORE_ACTION:
434 default:
435 return nullptr;
436 }
alexmos5a98a052016-01-06 00:15:02437
Lukasz Anforowicz82a5ca92019-10-24 18:45:37438 target->GetController().LoadURLWithParams(
439 NavigationController::LoadURLParams(params));
lukasza04130152016-10-21 20:26:32440 return target;
alexmos5a98a052016-01-06 00:15:02441}
442
[email protected]e3b10d12014-03-28 16:06:09443void Shell::LoadingStateChanged(WebContents* source,
Nate Chapin9aabf5f2021-11-12 00:31:19444 bool should_show_loading_ui) {
445 UpdateNavigationControls(should_show_loading_ui);
danakjde3e2a02020-05-12 16:51:20446 g_platform->SetIsLoading(this, source->IsLoading());
[email protected]e99ca5112011-09-26 17:22:54447}
448
Xiaohan Wangbd084422022-01-15 18:47:51449#if BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20450void Shell::SetOverlayMode(bool use_overlay_mode) {
451 g_platform->SetOverlayMode(this, use_overlay_mode);
452}
453#endif
454
Dave Tapuskaa4189512019-10-15 20:27:34455void Shell::EnterFullscreenModeForTab(
Mike Wasserman4ca09792020-05-29 17:44:43456 RenderFrameHost* requesting_frame,
Dave Tapuskaa4189512019-10-15 20:27:34457 const blink::mojom::FullscreenOptions& options) {
Mike Wasserman4ca09792020-05-29 17:44:43458 ToggleFullscreenModeForTab(WebContents::FromRenderFrameHost(requesting_frame),
459 true);
mlamouri7a78d6fd2015-01-17 13:23:53460}
461
462void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
463 ToggleFullscreenModeForTab(web_contents, false);
464}
465
[email protected]99c014c2012-11-27 12:03:42466void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
467 bool enter_fullscreen) {
Xiaohan Wangbd084422022-01-15 18:47:51468#if BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20469 g_platform->ToggleFullscreenModeForTab(this, web_contents, enter_fullscreen);
[email protected]99c014c2012-11-27 12:03:42470#endif
[email protected]99c014c2012-11-27 12:03:42471 if (is_fullscreen_ != enter_fullscreen) {
472 is_fullscreen_ = enter_fullscreen;
Lucas Furukawa Gadanie7649422021-02-03 03:04:32473 web_contents->GetMainFrame()
474 ->GetRenderViewHost()
Fady Samuel0b911822018-04-25 13:22:16475 ->GetWidget()
476 ->SynchronizeVisualProperties();
[email protected]99c014c2012-11-27 12:03:42477 }
478}
479
Lucas Furukawa Gadani4909f3c2019-06-18 22:36:52480bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) {
Xiaohan Wangbd084422022-01-15 18:47:51481#if BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20482 return g_platform->IsFullscreenForTabOrPending(this, web_contents);
[email protected]99c014c2012-11-27 12:03:42483#else
484 return is_fullscreen_;
485#endif
486}
487
Eric Willigers052f0432019-10-04 04:06:57488blink::mojom::DisplayMode Shell::GetDisplayMode(
489 const WebContents* web_contents) {
490 // TODO: should return blink::mojom::DisplayModeFullscreen wherever user puts
Lukasz Anforowicz52b93722018-06-20 16:11:39491 // a browser window into fullscreen (not only in case of renderer-initiated
492 // fullscreen mode): crbug.com/476874.
493 return IsFullscreenForTabOrPending(web_contents)
Eric Willigers052f0432019-10-04 04:06:57494 ? blink::mojom::DisplayMode::kFullscreen
495 : blink::mojom::DisplayMode::kBrowser;
mikhail.pozdnyakovc0e251b2015-04-15 06:51:12496}
497
Javier Fernández García-Boente13150a042022-04-04 21:08:22498#if !BUILDFLAG(IS_ANDROID)
499void Shell::RegisterProtocolHandler(RenderFrameHost* requesting_frame,
500 const std::string& protocol,
501 const GURL& url,
502 bool user_gesture) {
503 content::BrowserContext* context = requesting_frame->GetBrowserContext();
504 if (context->IsOffTheRecord())
505 return;
506
507 custom_handlers::ProtocolHandler handler =
508 custom_handlers::ProtocolHandler::CreateProtocolHandler(
509 protocol, url, GetProtocolHandlerSecurityLevel(requesting_frame));
510
511 // The parameters's normalization process defined in the spec has been already
512 // applied in the WebContentImpl class, so at this point it shouldn't be
513 // possible to create an invalid handler.
514 // https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
515 DCHECK(handler.IsValid());
516
517 custom_handlers::ProtocolHandlerRegistry* registry = custom_handlers::
518 SimpleProtocolHandlerRegistryFactory::GetForBrowserContext(context, true);
519 DCHECK(registry);
520 if (registry->SilentlyHandleRegisterHandlerRequest(handler))
521 return;
522
523 // FencedFrames can not register to handle any protocols.
524 if (requesting_frame->IsNestedWithinFencedFrame()) {
525 registry->OnIgnoreRegisterProtocolHandler(handler);
526 return;
527 }
528
529 // TODO(jfernandez): Are we interested at all on using the
530 // PermissionRequestManager in the ContentShell ?
531 registry->OnAcceptRegisterProtocolHandler(handler);
532}
533#endif
534
[email protected]f78439002012-11-28 14:45:59535void Shell::RequestToLockMouse(WebContents* web_contents,
536 bool user_gesture,
537 bool last_unlocked_by_target) {
Dave Tapuskab4998782020-10-08 17:22:47538 // Give the platform a chance to handle the lock request, if it doesn't
539 // indicate it handled it, allow the request.
540 if (!g_platform->HandleRequestToLockMouse(this, web_contents, user_gesture,
541 last_unlocked_by_target)) {
542 web_contents->GotResponseToLockMouseRequest(
543 blink::mojom::PointerLockResult::kSuccess);
544 }
[email protected]f78439002012-11-28 14:45:59545}
546
danakjde3e2a02020-05-12 16:51:20547void Shell::Close() {
548 // Shell is "self-owned" and destroys itself. The ShellPlatformDelegate
549 // has the chance to co-opt this and do its own destruction.
550 if (!g_platform->DestroyShell(this))
551 delete this;
552}
553
[email protected]9e00e6352012-07-30 17:05:18554void Shell::CloseContents(WebContents* source) {
555 Close();
556}
557
Lucas Furukawa Gadani4909f3c2019-06-18 22:36:52558bool Shell::CanOverscrollContent() {
[email protected]067310262012-11-22 14:30:41559#if defined(USE_AURA)
560 return true;
561#else
562 return false;
563#endif
564}
565
Mugdha Lakhani5f8de7cc2020-03-10 20:43:36566void Shell::NavigationStateChanged(WebContents* source,
567 InvalidateTypes changed_flags) {
568 if (changed_flags & INVALIDATE_TYPE_URL)
danakjde3e2a02020-05-12 16:51:20569 g_platform->SetAddressBarURL(this, source->GetVisibleURL());
[email protected]e99ca5112011-09-26 17:22:54570}
571
mathiash72a5e462014-11-19 08:18:50572JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
573 WebContents* source) {
danakj8de3b7492020-07-02 22:41:42574 if (!dialog_manager_)
575 dialog_manager_ = g_platform->CreateJavaScriptDialogManager(this);
576 if (!dialog_manager_)
577 dialog_manager_ = std::make_unique<ShellJavaScriptDialogManager>();
[email protected]71a88bb2013-02-01 22:05:15578 return dialog_manager_.get();
[email protected]f2210022012-03-29 00:36:08579}
580
Xiaohan Wangbd084422022-01-15 18:47:51581#if BUILDFLAG(IS_MAC)
Liviu Tinta40904052021-07-20 15:12:52582void Shell::DidNavigatePrimaryMainFramePostCommit(WebContents* contents) {
583 g_platform->DidNavigatePrimaryMainFramePostCommit(this, contents);
Xianzhu Wang0f021a82020-07-03 01:29:47584}
585
danakjde3e2a02020-05-12 16:51:20586bool Shell::HandleKeyboardEvent(WebContents* source,
587 const NativeWebKeyboardEvent& event) {
588 return g_platform->HandleKeyboardEvent(this, source, event);
589}
590#endif
591
avia90ae4e2016-11-11 20:49:33592bool Shell::DidAddMessageToConsole(WebContents* source,
Lowell Manners1de5242e2019-04-25 10:18:46593 blink::mojom::ConsoleMessageLevel log_level,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58594 const std::u16string& message,
avia90ae4e2016-11-11 20:49:33595 int32_t line_no,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58596 const std::u16string& source_id) {
Kent Tamuracd3ebc42018-05-16 06:44:22597 return switches::IsRunWebTestsSwitchPresent();
[email protected]efb5f572012-01-29 10:57:33598}
599
Lucas Furukawa Gadani06548fb2019-01-15 05:01:25600void Shell::PortalWebContentsCreated(WebContents* portal_web_contents) {
danakj8de3b7492020-07-02 22:41:42601 g_platform->DidCreateOrAttachWebContents(this, portal_web_contents);
Lucas Furukawa Gadani06548fb2019-01-15 05:01:25602}
603
Lukasz Anforowicz52b93722018-06-20 16:11:39604void Shell::RendererUnresponsive(
605 WebContents* source,
606 RenderWidgetHost* render_widget_host,
607 base::RepeatingClosure hang_monitor_restarter) {
danakj245441f2020-07-03 15:18:41608 LOG(WARNING) << "renderer unresponsive";
[email protected]5bf68f22012-08-31 07:38:10609}
610
[email protected]233567d2013-02-27 20:22:02611void Shell::ActivateContents(WebContents* contents) {
Xiaohan Wangbd084422022-01-15 18:47:51612#if !BUILDFLAG(IS_MAC)
danakjd4b48df52020-07-02 18:16:48613 // TODO(danakj): Move this to ShellPlatformDelegate.
danakj674bf1c02020-05-01 18:37:51614 contents->Focus();
615#else
616 // Mac headless mode is quite different than other platforms. Normally
617 // focusing the WebContents would cause the OS to focus the window. Because
618 // headless mac doesn't actually have system windows, we can't go down the
619 // normal path and have to fake it out in the browser process.
danakjde3e2a02020-05-12 16:51:20620 g_platform->ActivateContents(this, contents);
danakj674bf1c02020-05-01 18:37:51621#endif
[email protected]233567d2013-02-27 20:22:02622}
623
Dave Tapuskadfff7382021-04-23 19:46:41624bool Shell::IsBackForwardCacheSupported() {
625 return true;
626}
627
Hiroki Nakagawa4ae11b882022-02-03 03:24:11628bool Shell::IsPrerender2Supported(WebContents& web_contents) {
Lingqi Chi8159aec2021-06-15 01:46:03629 return true;
630}
631
Kevin McNee7422bc42020-02-20 18:49:55632std::unique_ptr<WebContents> Shell::ActivatePortalWebContents(
633 WebContents* predecessor_contents,
634 std::unique_ptr<WebContents> portal_contents) {
635 DCHECK_EQ(predecessor_contents, web_contents_.get());
636 portal_contents->SetDelegate(this);
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33637 web_contents_->SetDelegate(nullptr);
Kevin McNee7422bc42020-02-20 18:49:55638 std::swap(web_contents_, portal_contents);
danakjde3e2a02020-05-12 16:51:20639 g_platform->SetContents(this);
640 g_platform->SetAddressBarURL(this, web_contents_->GetVisibleURL());
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33641 LoadingStateChanged(web_contents_.get(), true);
Kevin McNee7422bc42020-02-20 18:49:55642 return portal_contents;
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33643}
644
Adithya Srinivasanb7204c82020-08-17 14:26:33645namespace {
646class PendingCallback : public base::RefCounted<PendingCallback> {
647 public:
648 explicit PendingCallback(base::OnceCallback<void()> cb)
649 : callback_(std::move(cb)) {}
650
651 private:
652 friend class base::RefCounted<PendingCallback>;
653 ~PendingCallback() { std::move(callback_).Run(); }
654 base::OnceCallback<void()> callback_;
655};
656} // namespace
657
658void Shell::UpdateInspectedWebContentsIfNecessary(
659 content::WebContents* old_contents,
660 content::WebContents* new_contents,
661 base::OnceCallback<void()> callback) {
662 scoped_refptr<PendingCallback> pending_callback =
663 base::MakeRefCounted<PendingCallback>(std::move(callback));
664 for (auto* shell_devtools_bindings :
665 ShellDevToolsBindings::GetInstancesForWebContents(old_contents)) {
666 shell_devtools_bindings->UpdateInspectedWebContents(
Daniel Chengb7b2f5b2021-09-25 21:37:19667 new_contents, base::BindOnce([](scoped_refptr<PendingCallback>) {},
668 pending_callback));
Adithya Srinivasanb7204c82020-08-17 14:26:33669 }
670}
671
Lukasz Anforowicz82a5ca92019-10-24 18:45:37672bool Shell::ShouldAllowRunningInsecureContent(WebContents* web_contents,
673 bool allowed_per_prefs,
674 const url::Origin& origin,
675 const GURL& resource_url) {
danakj8de3b7492020-07-02 22:41:42676 if (allowed_per_prefs)
677 return true;
carloskd9d97942017-02-16 08:58:09678
danakj8de3b7492020-07-02 22:41:42679 return g_platform->ShouldAllowRunningInsecureContent(this);
carloskd9d97942017-02-16 08:58:09680}
681
François Beaufort1388f2892022-01-29 08:22:47682PictureInPictureResult Shell::EnterPictureInPicture(WebContents* web_contents) {
Becca Hughes112832e2019-06-11 17:19:02683 // During tests, returning success to pretend the window was created and allow
684 // tests to run accordingly.
685 if (!switches::IsRunWebTestsSwitchPresent())
686 return PictureInPictureResult::kNotSupported;
Becca Hughes112832e2019-06-11 17:19:02687 return PictureInPictureResult::kSuccess;
Mounir Lamouri11e9ef432018-05-22 03:10:16688}
689
Bo Liu300c6052018-06-12 04:46:07690bool Shell::ShouldResumeRequestsForCreatedWindow() {
691 return !delay_popup_contents_delegate_for_testing_;
692}
693
danakjee2390a82020-06-10 16:53:37694void Shell::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
695 DCHECK(source == web_contents()); // There's only one WebContents per Shell.
696
697 if (switches::IsRunWebTestsSwitchPresent()) {
698 // Note that chrome drops these requests on normal windows.
699 // TODO(danakj): The position is dropped here but we use the size. Web tests
700 // can't move the window in headless mode anyways, but maybe we should be
701 // letting them pretend?
702 g_platform->ResizeWebContent(this, bounds.size());
703 }
704}
705
pdrcab84ee2015-03-13 21:47:04706gfx::Size Shell::GetShellDefaultSize() {
danakj6c16fe92020-09-18 23:51:32707 static gfx::Size default_shell_size; // Only go through this method once.
708
pdrcab84ee2015-03-13 21:47:04709 if (!default_shell_size.IsEmpty())
710 return default_shell_size;
danakj6c16fe92020-09-18 23:51:32711
pdrcab84ee2015-03-13 21:47:04712 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
713 if (command_line->HasSwitch(switches::kContentShellHostWindowSize)) {
714 const std::string size_str = command_line->GetSwitchValueASCII(
arthursonzogni75ede192021-07-06 14:45:46715 switches::kContentShellHostWindowSize);
pdrcab84ee2015-03-13 21:47:04716 int width, height;
danakj6c16fe92020-09-18 23:51:32717 if (sscanf(size_str.c_str(), "%dx%d", &width, &height) == 2) {
718 default_shell_size = gfx::Size(width, height);
719 } else {
720 LOG(ERROR) << "Invalid size \"" << size_str << "\" given to --"
721 << switches::kContentShellHostWindowSize;
722 }
723 }
724
725 if (default_shell_size.IsEmpty()) {
arthursonzogni75ede192021-07-06 14:45:46726 default_shell_size =
727 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
pdrcab84ee2015-03-13 21:47:04728 }
danakj6c16fe92020-09-18 23:51:32729
pdrcab84ee2015-03-13 21:47:04730 return default_shell_size;
731}
732
Xiaohan Wangbd084422022-01-15 18:47:51733#if BUILDFLAG(IS_ANDROID)
danakjde3e2a02020-05-12 16:51:20734void Shell::LoadProgressChanged(double progress) {
735 g_platform->LoadProgressChanged(this, progress);
736}
737#endif
738
Avi Drissman93002212017-09-27 03:20:52739void Shell::TitleWasSet(NavigationEntry* entry) {
[email protected]1ef02d242013-10-07 16:18:53740 if (entry)
danakjde3e2a02020-05-12 16:51:20741 g_platform->SetTitle(this, entry->GetTitle());
[email protected]aecc085b2012-06-01 18:15:53742}
743
[email protected]9fbd3f862011-09-20 23:31:34744} // namespace content