blob: 705b24a8ea736dc38054ac58fd9cf50de01eea5e [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>
10#include <string>
11#include <utility>
12
[email protected]efb5f572012-01-29 10:57:3313#include "base/command_line.h"
skyostil95082a62015-06-05 19:53:0714#include "base/location.h"
avi66a07722015-12-25 23:38:1215#include "base/macros.h"
Wez9a58a152018-06-07 18:59:3316#include "base/no_destructor.h"
fdoray896bea12016-06-10 15:52:0117#include "base/run_loop.h"
skyostil95082a62015-06-05 19:53:0718#include "base/single_thread_task_runner.h"
[email protected]21aa99682013-06-11 07:17:0119#include "base/strings/string_number_conversions.h"
20#include "base/strings/string_util.h"
21#include "base/strings/stringprintf.h"
[email protected]74ebfb12013-06-07 20:48:0022#include "base/strings/utf_string_conversions.h"
gab30f26df2016-05-11 19:37:5523#include "base/threading/thread_task_runner_handle.h"
avi66a07722015-12-25 23:38:1224#include "build/build_config.h"
[email protected]b50452f2014-08-18 12:31:4425#include "content/public/browser/devtools_agent_host.h"
[email protected]0b659b32012-03-26 21:29:3226#include "content/public/browser/navigation_controller.h"
[email protected]b7c504c2013-05-07 14:42:1227#include "content/public/browser/navigation_entry.h"
Becca Hughes112832e2019-06-11 17:19:0228#include "content/public/browser/picture_in_picture_window_controller.h"
arthursonzognib93a4472020-04-10 07:38:0029#include "content/public/browser/presentation_receiver_flags.h"
Yutaka Hirano2109e582018-02-14 07:24:4630#include "content/public/browser/render_process_host.h"
[email protected]0b659b32012-03-26 21:29:3231#include "content/public/browser/render_view_host.h"
avif9ab5d942015-10-15 14:05:4432#include "content/public/browser/render_widget_host.h"
Xianzhu Wang6be66b012020-05-06 17:17:2533#include "content/public/browser/renderer_preferences_util.h"
[email protected]0b659b32012-03-26 21:29:3234#include "content/public/browser/web_contents.h"
guoweis8efb6d892015-10-12 18:26:1735#include "content/public/common/content_switches.h"
danakjde3e2a02020-05-12 16:51:2036#include "content/shell/app/resource.h"
[email protected]de7d61ff2013-08-20 11:30:4137#include "content/shell/browser/shell_content_browser_client.h"
38#include "content/shell/browser/shell_devtools_frontend.h"
39#include "content/shell/browser/shell_javascript_dialog_manager.h"
Jun Cai149002e2019-05-09 23:13:0740#include "content/shell/browser/web_test/fake_bluetooth_scanning_prompt.h"
Kent Tamuraf92649d882018-12-03 09:07:4741#include "content/shell/browser/web_test/secondary_test_window_observer.h"
42#include "content/shell/browser/web_test/web_test_bluetooth_chooser_factory.h"
Gyuyoung Kim26c7bc92020-04-29 00:53:0043#include "content/shell/browser/web_test/web_test_control_host.h"
Kent Tamuraf92649d882018-12-03 09:07:4744#include "content/shell/browser/web_test/web_test_devtools_bindings.h"
45#include "content/shell/browser/web_test/web_test_javascript_dialog_manager.h"
[email protected]b7c504c2013-05-07 14:42:1246#include "content/shell/common/shell_switches.h"
Kent Tamurade503112018-12-04 08:57:4047#include "content/shell/common/web_test/web_test_switches.h"
Scott Violeta35f9a42018-03-22 22:00:4448#include "media/media_buildflags.h"
Antonio Gomesb5bf548f2019-09-12 17:40:1549#include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
Leon Hanc819dc62019-01-28 04:30:1950#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
[email protected]9fbd3f862011-09-20 23:31:3451
[email protected]9fbd3f862011-09-20 23:31:3452namespace content {
53
Wezcbf4a042018-06-13 16:29:1254// Null until/unless the default main message loop is running.
55base::NoDestructor<base::OnceClosure> g_quit_main_message_loop;
Wez9a58a152018-06-07 18:59:3356
pdrcab84ee2015-03-13 21:47:0457const int kDefaultTestWindowWidthDip = 800;
58const int kDefaultTestWindowHeightDip = 600;
[email protected]1e57cab2013-05-28 04:26:1159
[email protected]e99ca5112011-09-26 17:22:5460std::vector<Shell*> Shell::windows_;
danakja9fe91c2019-05-01 19:02:2961base::OnceCallback<void(Shell*)> Shell::shell_created_callback_;
[email protected]9fbd3f862011-09-20 23:31:3462
danakjde3e2a02020-05-12 16:51:2063ShellPlatformDelegate* g_platform;
64
[email protected]7fff43e2013-05-21 20:21:1065class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
66 public:
67 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
68 : WebContentsObserver(web_contents),
69 shell_(shell) {
70 }
71
72 // WebContentsObserver
dchenge933b3e2014-10-21 11:44:0973 void WebContentsDestroyed() override {
[email protected]7fff43e2013-05-21 20:21:1074 shell_->OnDevToolsWebContentsDestroyed();
75 }
76
77 private:
78 Shell* shell_;
79
80 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
81};
82
Bo Liu300c6052018-06-12 04:46:0783Shell::Shell(std::unique_ptr<WebContents> web_contents,
84 bool should_set_delegate)
erikchenbee5c9622018-04-27 19:30:2585 : WebContentsObserver(web_contents.get()),
danakjde3e2a02020-05-12 16:51:2086 web_contents_(std::move(web_contents)) {
Bo Liu300c6052018-06-12 04:46:0787 if (should_set_delegate)
88 web_contents_->SetDelegate(this);
arthursonzognifdd49912017-08-31 08:55:2689
Kent Tamuracd3ebc42018-05-16 06:44:2290 if (switches::IsRunWebTestsSwitchPresent()) {
jonross26185702019-04-08 18:54:1091 headless_ = !base::CommandLine::ForCurrentProcess()->HasSwitch(
92 switches::kDisableHeadlessMode);
Xianzhu Wang6be66b012020-05-06 17:17:2593 } else {
94 UpdateFontRendererPreferencesFromSystemSettings(
95 web_contents_->GetMutableRendererPrefs());
Francois Doraye6161152018-03-27 22:05:3796 }
Pavel Feldmanc7cd063c2017-10-06 20:04:2897
[email protected]9e00e6352012-07-30 17:05:1898 windows_.push_back(this);
99
danakja9fe91c2019-05-01 19:02:29100 if (shell_created_callback_)
101 std::move(shell_created_callback_).Run(this);
[email protected]9fbd3f862011-09-20 23:31:34102}
103
104Shell::~Shell() {
danakjde3e2a02020-05-12 16:51:20105 g_platform->CleanUp(this);
[email protected]e99ca5112011-09-26 17:22:54106
107 for (size_t i = 0; i < windows_.size(); ++i) {
108 if (windows_[i] == this) {
109 windows_.erase(windows_.begin() + i);
110 break;
111 }
112 }
[email protected]11a65b692012-03-30 11:29:16113
danakjde3e2a02020-05-12 16:51:20114 // Always destroy WebContents before destroying ShellPlatformDelegate.
115 // WebContents destruction sequence may depend on the resources destroyed with
116 // ShellPlatformDelegate (e.g. the display::Screen singleton).
Sergey Ulanovf0875d12019-01-03 20:33:23117 web_contents_->SetDelegate(nullptr);
118 web_contents_.reset();
119
Wez9a58a152018-06-07 18:59:33120 if (windows_.empty()) {
Peter Kastinged599662020-05-18 18:40:42121 delete g_platform;
122 g_platform = nullptr;
danakjde3e2a02020-05-12 16:51:20123
Yutaka Hirano2109e582018-02-14 07:24:46124 for (auto it = RenderProcessHost::AllHostsIterator(); !it.IsAtEnd();
125 it.Advance()) {
126 it.GetCurrentValue()->DisableKeepAliveRefCount();
127 }
Wezcbf4a042018-06-13 16:29:12128 if (*g_quit_main_message_loop)
129 std::move(*g_quit_main_message_loop).Run();
[email protected]b53adf452014-02-07 12:55:08130 }
[email protected]9fbd3f862011-09-20 23:31:34131}
132
erikchenbee5c9622018-04-27 19:30:25133Shell* Shell::CreateShell(std::unique_ptr<WebContents> web_contents,
Bo Liu300c6052018-06-12 04:46:07134 const gfx::Size& initial_size,
135 bool should_set_delegate) {
erikchenbee5c9622018-04-27 19:30:25136 WebContents* raw_web_contents = web_contents.get();
Bo Liu300c6052018-06-12 04:46:07137 Shell* shell = new Shell(std::move(web_contents), should_set_delegate);
danakjde3e2a02020-05-12 16:51:20138 g_platform->CreatePlatformWindow(shell, initial_size);
139 g_platform->SetContents(shell);
[email protected]1596efb2013-01-17 22:13:01140
creisb6561df2016-02-11 20:20:54141 // Note: Do not make RenderFrameHost or RenderViewHost specific state changes
142 // here, because they will be forgotten after a cross-process navigation. Use
143 // RenderFrameCreated or RenderViewCreated instead.
Kent Tamuracd3ebc42018-05-16 06:44:22144 if (switches::IsRunWebTestsSwitchPresent()) {
erikchenbee5c9622018-04-27 19:30:25145 raw_web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
Bruce Long1e3e1f542019-10-16 17:56:28146 raw_web_contents->SyncRendererPrefs();
[email protected]1596efb2013-01-17 22:13:01147 }
148
lukasza381b0492016-03-10 16:48:43149 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
guoweis4ee48592015-12-02 06:37:07150 if (command_line->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) {
erikchenbee5c9622018-04-27 19:30:25151 raw_web_contents->GetMutableRendererPrefs()->webrtc_ip_handling_policy =
guoweis4ee48592015-12-02 06:37:07152 command_line->GetSwitchValueASCII(
153 switches::kForceWebRtcIPHandlingPolicy);
guoweis8efb6d892015-10-12 18:26:17154 }
guoweis8efb6d892015-10-12 18:26:17155
[email protected]3fd84032012-01-12 18:20:17156 return shell;
157}
158
[email protected]11a65b692012-03-30 11:29:16159void Shell::CloseAllWindows() {
[email protected]b50452f2014-08-18 12:31:44160 DevToolsAgentHost::DetachAllClients();
Wezcbf4a042018-06-13 16:29:12161
Peter Kastinged599662020-05-18 18:40:42162 std::vector<Shell*> open_windows(windows_);
163 for (Shell* open_window : open_windows)
164 open_window->Close();
165 DCHECK(windows_.empty());
Wezcbf4a042018-06-13 16:29:12166
Peter Kastinged599662020-05-18 18:40:42167 // Pump the message loop to allow window teardown tasks to run.
168 base::RunLoop().RunUntilIdle();
[email protected]11a65b692012-03-30 11:29:16169}
170
Wezcbf4a042018-06-13 16:29:12171void Shell::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
172 *g_quit_main_message_loop = std::move(quit_closure);
173}
174
Wez7d3eb012018-06-20 22:51:28175void Shell::QuitMainMessageLoopForTesting() {
Wezc93f15a92020-02-25 21:57:44176 if (*g_quit_main_message_loop)
177 std::move(*g_quit_main_message_loop).Run();
Wez7d3eb012018-06-20 22:51:28178}
179
[email protected]9e00e6352012-07-30 17:05:18180void Shell::SetShellCreatedCallback(
danakja9fe91c2019-05-01 19:02:29181 base::OnceCallback<void(Shell*)> shell_created_callback) {
182 DCHECK(!shell_created_callback_);
Tommy Nyquist4b749d02018-03-20 21:46:29183 shell_created_callback_ = std::move(shell_created_callback);
[email protected]9e00e6352012-07-30 17:05:18184}
185
danakjde3e2a02020-05-12 16:51:20186// static
187bool Shell::ShouldHideToolbar() {
188 return base::CommandLine::ForCurrentProcess()->HasSwitch(
189 switches::kContentShellHideToolbar);
190}
191
David Benjaminf62c6662019-03-21 20:25:04192Shell* Shell::FromWebContents(WebContents* web_contents) {
193 for (Shell* window : windows_) {
194 if (window->web_contents() && window->web_contents() == web_contents) {
195 return window;
[email protected]74830f02012-01-30 22:27:04196 }
197 }
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28198 return nullptr;
[email protected]74830f02012-01-30 22:27:04199}
200
danakjde3e2a02020-05-12 16:51:20201void Shell::Initialize(std::unique_ptr<ShellPlatformDelegate> platform) {
202 g_platform = platform.release();
203 g_platform->Initialize(GetShellDefaultSize());
[email protected]6153b272013-01-25 22:29:23204}
205
[email protected]a2904092013-10-15 04:53:59206gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
207 if (!initial_size.IsEmpty())
208 return initial_size;
pdrcab84ee2015-03-13 21:47:04209 return GetShellDefaultSize();
[email protected]a2904092013-10-15 04:53:59210}
211
[email protected]bdcf9152012-07-19 17:43:21212Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
[email protected]e99ca5112011-09-26 17:22:54213 const GURL& url,
lukasza04130152016-10-21 20:26:32214 const scoped_refptr<SiteInstance>& site_instance,
[email protected]cdb806722013-01-10 14:18:23215 const gfx::Size& initial_size) {
[email protected]54944cde2012-12-09 09:24:59216 WebContents::CreateParams create_params(browser_context, site_instance);
mark a. foltzef394fce2017-10-21 09:11:02217 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
218 switches::kForcePresentationReceiverForTesting)) {
219 create_params.starting_sandbox_flags =
arthursonzognib93a4472020-04-10 07:38:00220 content::kPresentationReceiverSandboxFlags;
mark a. foltzef394fce2017-10-21 09:11:02221 }
erikchenbee5c9622018-04-27 19:30:25222 std::unique_ptr<WebContents> web_contents =
Erik Chenbb8e738e2018-04-28 14:10:43223 WebContents::Create(create_params);
erikchenbee5c9622018-04-27 19:30:25224 Shell* shell =
danakjfc5184932019-09-12 18:08:32225 CreateShell(std::move(web_contents), AdjustWindowSize(initial_size),
Bo Liu300c6052018-06-12 04:46:07226 true /* should_set_delegate */);
[email protected]e99ca5112011-09-26 17:22:54227 if (!url.is_empty())
228 shell->LoadURL(url);
[email protected]9fbd3f862011-09-20 23:31:34229 return shell;
230}
231
Daniel Murphy16ed0782018-05-26 00:15:13232Shell* Shell::CreateNewWindowWithSessionStorageNamespace(
233 BrowserContext* browser_context,
234 const GURL& url,
235 const scoped_refptr<SiteInstance>& site_instance,
236 const gfx::Size& initial_size,
237 scoped_refptr<SessionStorageNamespace> session_storage_namespace) {
238 WebContents::CreateParams create_params(browser_context, site_instance);
239 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
240 switches::kForcePresentationReceiverForTesting)) {
241 create_params.starting_sandbox_flags =
arthursonzognib93a4472020-04-10 07:38:00242 content::kPresentationReceiverSandboxFlags;
Daniel Murphy16ed0782018-05-26 00:15:13243 }
Daniel Murphy16ed0782018-05-26 00:15:13244 std::map<std::string, scoped_refptr<SessionStorageNamespace>>
245 session_storages;
246 session_storages[""] = session_storage_namespace;
247 std::unique_ptr<WebContents> web_contents =
248 WebContents::CreateWithSessionStorage(create_params, session_storages);
249 Shell* shell =
danakjfc5184932019-09-12 18:08:32250 CreateShell(std::move(web_contents), AdjustWindowSize(initial_size),
Bo Liu300c6052018-06-12 04:46:07251 true /* should_set_delegate */);
Daniel Murphy16ed0782018-05-26 00:15:13252 if (!url.is_empty())
253 shell->LoadURL(url);
254 return shell;
255}
256
danakj24577b12020-05-13 22:38:18257void Shell::RenderViewReady() {
258 g_platform->RenderViewReady(this);
259}
260
[email protected]9fbd3f862011-09-20 23:31:34261void Shell::LoadURL(const GURL& url) {
Alex Moshchuk7e26eca2018-03-03 01:34:29262 LoadURLForFrame(
263 url, std::string(),
264 ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
265 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
[email protected]d2494ff2013-02-20 08:22:37266}
267
Alex Moshchuk7e26eca2018-03-03 01:34:29268void Shell::LoadURLForFrame(const GURL& url,
269 const std::string& frame_name,
270 ui::PageTransition transition_type) {
[email protected]d2494ff2013-02-20 08:22:37271 NavigationController::LoadURLParams params(url);
[email protected]d2494ff2013-02-20 08:22:37272 params.frame_name = frame_name;
Alex Moshchuk7e26eca2018-03-03 01:34:29273 params.transition_type = transition_type;
[email protected]d2494ff2013-02-20 08:22:37274 web_contents_->GetController().LoadURLWithParams(params);
[email protected]9fbd3f862011-09-20 23:31:34275}
276
[email protected]76bdecb2014-04-16 17:58:08277void Shell::LoadDataWithBaseURL(const GURL& url, const std::string& data,
278 const GURL& base_url) {
boliuec93ea92016-02-17 22:23:07279 bool load_as_string = false;
280 LoadDataWithBaseURLInternal(url, data, base_url, load_as_string);
281}
282
283#if defined(OS_ANDROID)
284void Shell::LoadDataAsStringWithBaseURL(const GURL& url,
285 const std::string& data,
286 const GURL& base_url) {
287 bool load_as_string = true;
288 LoadDataWithBaseURLInternal(url, data, base_url, load_as_string);
289}
290#endif
291
292void Shell::LoadDataWithBaseURLInternal(const GURL& url,
293 const std::string& data,
294 const GURL& base_url,
295 bool load_as_string) {
296#if !defined(OS_ANDROID)
297 DCHECK(!load_as_string); // Only supported on Android.
298#endif
299
300 NavigationController::LoadURLParams params(GURL::EmptyGURL());
301 const std::string data_url_header = "data:text/html;charset=utf-8,";
302 if (load_as_string) {
303 params.url = GURL(data_url_header);
304 std::string data_url_as_string = data_url_header + data;
305#if defined(OS_ANDROID)
306 params.data_url_as_string =
307 base::RefCountedString::TakeString(&data_url_as_string);
308#endif
309 } else {
310 params.url = GURL(data_url_header + data);
311 }
312
[email protected]76bdecb2014-04-16 17:58:08313 params.load_type = NavigationController::LOAD_TYPE_DATA;
314 params.base_url_for_data_url = base_url;
315 params.virtual_url_for_data_url = url;
316 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
317 web_contents_->GetController().LoadURLWithParams(params);
[email protected]76bdecb2014-04-16 17:58:08318}
319
[email protected]a2904092013-10-15 04:53:59320void Shell::AddNewContents(WebContents* source,
erikchenbee5c9622018-04-27 19:30:25321 std::unique_ptr<WebContents> new_contents,
Joel Hockey891e88062020-04-30 05:38:44322 const GURL& target_url,
[email protected]a2904092013-10-15 04:53:59323 WindowOpenDisposition disposition,
bokan107a47f2015-02-03 23:23:39324 const gfx::Rect& initial_rect,
[email protected]a2904092013-10-15 04:53:59325 bool user_gesture,
326 bool* was_blocked) {
erikchenbee5c9622018-04-27 19:30:25327 WebContents* raw_new_contents = new_contents.get();
Bo Liu300c6052018-06-12 04:46:07328 CreateShell(
329 std::move(new_contents), AdjustWindowSize(initial_rect.size()),
330 !delay_popup_contents_delegate_for_testing_ /* should_set_delegate */);
Kent Tamuracd3ebc42018-05-16 06:44:22331 if (switches::IsRunWebTestsSwitchPresent())
erikchenbee5c9622018-04-27 19:30:25332 SecondaryTestWindowObserver::CreateForWebContents(raw_new_contents);
[email protected]a2904092013-10-15 04:53:59333}
334
[email protected]9fbd3f862011-09-20 23:31:34335void Shell::GoBackOrForward(int offset) {
[email protected]0b659b32012-03-26 21:29:32336 web_contents_->GetController().GoToOffset(offset);
[email protected]9fbd3f862011-09-20 23:31:34337}
338
339void Shell::Reload() {
toyoshim6142d96f2016-12-19 09:07:25340 web_contents_->GetController().Reload(ReloadType::NORMAL, false);
[email protected]9fbd3f862011-09-20 23:31:34341}
342
toyoshime5aaf6a2016-05-18 08:07:48343void Shell::ReloadBypassingCache() {
toyoshim6142d96f2016-12-19 09:07:25344 web_contents_->GetController().Reload(ReloadType::BYPASSING_CACHE, false);
toyoshime5aaf6a2016-05-18 08:07:48345}
346
[email protected]9fbd3f862011-09-20 23:31:34347void Shell::Stop() {
[email protected]0b659b32012-03-26 21:29:32348 web_contents_->Stop();
[email protected]9fbd3f862011-09-20 23:31:34349}
350
[email protected]e3b10d12014-03-28 16:06:09351void Shell::UpdateNavigationControls(bool to_different_document) {
[email protected]0b659b32012-03-26 21:29:32352 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
353 int max_index = web_contents_->GetController().GetEntryCount() - 1;
[email protected]9fbd3f862011-09-20 23:31:34354
danakjde3e2a02020-05-12 16:51:20355 g_platform->EnableUIControl(this, ShellPlatformDelegate::BACK_BUTTON,
356 current_index > 0);
357 g_platform->EnableUIControl(this, ShellPlatformDelegate::FORWARD_BUTTON,
358 current_index < max_index);
359 g_platform->EnableUIControl(
360 this, ShellPlatformDelegate::STOP_BUTTON,
[email protected]e3b10d12014-03-28 16:06:09361 to_different_document && web_contents_->IsLoading());
[email protected]9fbd3f862011-09-20 23:31:34362}
363
[email protected]7c17b6992012-08-09 16:16:30364void Shell::ShowDevTools() {
mohsen6eb57fb2016-07-22 03:14:08365 if (!devtools_frontend_) {
366 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents());
367 devtools_observer_.reset(new DevToolsWebContentsObserver(
368 this, devtools_frontend_->frontend_shell()->web_contents()));
369 }
[email protected]3142e5d2014-02-07 00:54:46370
mohsen6eb57fb2016-07-22 03:14:08371 devtools_frontend_->Activate();
[email protected]7c17b6992012-08-09 16:16:30372}
373
[email protected]001841c92012-12-11 17:00:13374void Shell::CloseDevTools() {
[email protected]0773e0c2013-01-25 15:57:57375 if (!devtools_frontend_)
[email protected]001841c92012-12-11 17:00:13376 return;
[email protected]7fff43e2013-05-21 20:21:10377 devtools_observer_.reset();
[email protected]0773e0c2013-01-25 15:57:57378 devtools_frontend_->Close();
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28379 devtools_frontend_ = nullptr;
[email protected]001841c92012-12-11 17:00:13380}
381
danakjde3e2a02020-05-12 16:51:20382void Shell::ResizeWebContentForTests(const gfx::Size& content_size) {
383 g_platform->ResizeWebContent(this, content_size);
384}
danakjde3e2a02020-05-12 16:51:20385
[email protected]9fbd3f862011-09-20 23:31:34386gfx::NativeView Shell::GetContentView() {
[email protected]59383c782013-04-17 16:43:27387 if (!web_contents_)
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28388 return nullptr;
[email protected]fc2b46b2014-05-03 16:33:45389 return web_contents_->GetNativeView();
[email protected]9fbd3f862011-09-20 23:31:34390}
391
danakjde3e2a02020-05-12 16:51:20392#if !defined(OS_ANDROID)
393gfx::NativeWindow Shell::window() {
394 return g_platform->GetNativeWindow(this);
395}
396#endif
397
398#if defined(OS_MACOSX)
399void Shell::ActionPerformed(int control) {
400 switch (control) {
401 case IDC_NAV_BACK:
402 GoBackOrForward(-1);
403 break;
404 case IDC_NAV_FORWARD:
405 GoBackOrForward(1);
406 break;
407 case IDC_NAV_RELOAD:
408 Reload();
409 break;
410 case IDC_NAV_STOP:
411 Stop();
412 break;
413 }
414}
415
416void Shell::URLEntered(const std::string& url_string) {
417 if (!url_string.empty()) {
418 GURL url(url_string);
419 if (!url.has_scheme())
420 url = GURL("http://" + url_string);
421 LoadURL(url);
422 }
423}
424#endif
425
alexmos5a98a052016-01-06 00:15:02426WebContents* Shell::OpenURLFromTab(WebContents* source,
427 const OpenURLParams& params) {
lukasza04130152016-10-21 20:26:32428 WebContents* target = nullptr;
429 switch (params.disposition) {
430 case WindowOpenDisposition::CURRENT_TAB:
431 target = source;
432 break;
433
434 // Normally, the difference between NEW_POPUP and NEW_WINDOW is that a popup
435 // should have no toolbar, no status bar, no menu bar, no scrollbars and be
436 // not resizable. For simplicity and to enable new testing scenarios in
Kent Tamura21d1de62018-12-10 04:45:20437 // content shell and web tests, popups don't get special treatment below
lukasza04130152016-10-21 20:26:32438 // (i.e. they will have a toolbar and other things described here).
439 case WindowOpenDisposition::NEW_POPUP:
lukaszabe2f0da2017-04-25 00:43:00440 case WindowOpenDisposition::NEW_WINDOW:
Kent Tamura21d1de62018-12-10 04:45:20441 // content_shell doesn't really support tabs, but some web tests use
lukaszabe2f0da2017-04-25 00:43:00442 // middle click (which translates into kNavigationPolicyNewBackgroundTab),
443 // so we treat the cases below just like a NEW_WINDOW disposition.
444 case WindowOpenDisposition::NEW_BACKGROUND_TAB:
445 case WindowOpenDisposition::NEW_FOREGROUND_TAB: {
lukasza04130152016-10-21 20:26:32446 Shell* new_window =
447 Shell::CreateNewWindow(source->GetBrowserContext(),
448 GURL(), // Don't load anything just yet.
449 params.source_site_instance,
450 gfx::Size()); // Use default size.
451 target = new_window->web_contents();
Kent Tamuracd3ebc42018-05-16 06:44:22452 if (switches::IsRunWebTestsSwitchPresent())
lukasza04130152016-10-21 20:26:32453 SecondaryTestWindowObserver::CreateForWebContents(target);
454 break;
455 }
456
457 // No tabs in content_shell:
458 case WindowOpenDisposition::SINGLETON_TAB:
lukasza04130152016-10-21 20:26:32459 // No incognito mode in content_shell:
460 case WindowOpenDisposition::OFF_THE_RECORD:
Kent Tamura21d1de62018-12-10 04:45:20461 // TODO(lukasza): Investigate if some web tests might need support for
lukasza04130152016-10-21 20:26:32462 // SAVE_TO_DISK disposition. This would probably require that
Gyuyoung Kim26c7bc92020-04-29 00:53:00463 // WebTestControlHost always sets up and cleans up a temporary directory
lukasza04130152016-10-21 20:26:32464 // as the default downloads destinations for the duration of a test.
465 case WindowOpenDisposition::SAVE_TO_DISK:
466 // Ignoring requests with disposition == IGNORE_ACTION...
467 case WindowOpenDisposition::IGNORE_ACTION:
468 default:
469 return nullptr;
470 }
alexmos5a98a052016-01-06 00:15:02471
Lukasz Anforowicz82a5ca92019-10-24 18:45:37472 target->GetController().LoadURLWithParams(
473 NavigationController::LoadURLParams(params));
lukasza04130152016-10-21 20:26:32474 return target;
alexmos5a98a052016-01-06 00:15:02475}
476
[email protected]e3b10d12014-03-28 16:06:09477void Shell::LoadingStateChanged(WebContents* source,
478 bool to_different_document) {
479 UpdateNavigationControls(to_different_document);
danakjde3e2a02020-05-12 16:51:20480 g_platform->SetIsLoading(this, source->IsLoading());
[email protected]e99ca5112011-09-26 17:22:54481}
482
danakjde3e2a02020-05-12 16:51:20483#if defined(OS_ANDROID)
484void Shell::SetOverlayMode(bool use_overlay_mode) {
485 g_platform->SetOverlayMode(this, use_overlay_mode);
486}
487#endif
488
Dave Tapuskaa4189512019-10-15 20:27:34489void Shell::EnterFullscreenModeForTab(
490 WebContents* web_contents,
491 const GURL& origin,
492 const blink::mojom::FullscreenOptions& options) {
mlamouri7a78d6fd2015-01-17 13:23:53493 ToggleFullscreenModeForTab(web_contents, true);
494}
495
496void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
497 ToggleFullscreenModeForTab(web_contents, false);
498}
499
[email protected]99c014c2012-11-27 12:03:42500void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
501 bool enter_fullscreen) {
502#if defined(OS_ANDROID)
danakjde3e2a02020-05-12 16:51:20503 g_platform->ToggleFullscreenModeForTab(this, web_contents, enter_fullscreen);
[email protected]99c014c2012-11-27 12:03:42504#endif
[email protected]99c014c2012-11-27 12:03:42505 if (is_fullscreen_ != enter_fullscreen) {
506 is_fullscreen_ = enter_fullscreen;
Fady Samuel0b911822018-04-25 13:22:16507 web_contents->GetRenderViewHost()
508 ->GetWidget()
509 ->SynchronizeVisualProperties();
[email protected]99c014c2012-11-27 12:03:42510 }
511}
512
Lucas Furukawa Gadani4909f3c2019-06-18 22:36:52513bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) {
[email protected]99c014c2012-11-27 12:03:42514#if defined(OS_ANDROID)
danakjde3e2a02020-05-12 16:51:20515 return g_platform->IsFullscreenForTabOrPending(this, web_contents);
[email protected]99c014c2012-11-27 12:03:42516#else
517 return is_fullscreen_;
518#endif
519}
520
Eric Willigers052f0432019-10-04 04:06:57521blink::mojom::DisplayMode Shell::GetDisplayMode(
522 const WebContents* web_contents) {
523 // TODO: should return blink::mojom::DisplayModeFullscreen wherever user puts
Lukasz Anforowicz52b93722018-06-20 16:11:39524 // a browser window into fullscreen (not only in case of renderer-initiated
525 // fullscreen mode): crbug.com/476874.
526 return IsFullscreenForTabOrPending(web_contents)
Eric Willigers052f0432019-10-04 04:06:57527 ? blink::mojom::DisplayMode::kFullscreen
528 : blink::mojom::DisplayMode::kBrowser;
mikhail.pozdnyakovc0e251b2015-04-15 06:51:12529}
530
[email protected]f78439002012-11-28 14:45:59531void Shell::RequestToLockMouse(WebContents* web_contents,
532 bool user_gesture,
533 bool last_unlocked_by_target) {
James Hollyerd5c9de462020-03-10 19:02:45534 web_contents->GotResponseToLockMouseRequest(
535 blink::mojom::PointerLockResult::kSuccess);
[email protected]f78439002012-11-28 14:45:59536}
537
danakjde3e2a02020-05-12 16:51:20538void Shell::Close() {
539 // Shell is "self-owned" and destroys itself. The ShellPlatformDelegate
540 // has the chance to co-opt this and do its own destruction.
541 if (!g_platform->DestroyShell(this))
542 delete this;
543}
544
[email protected]9e00e6352012-07-30 17:05:18545void Shell::CloseContents(WebContents* source) {
546 Close();
547}
548
Lucas Furukawa Gadani4909f3c2019-06-18 22:36:52549bool Shell::CanOverscrollContent() {
[email protected]067310262012-11-22 14:30:41550#if defined(USE_AURA)
551 return true;
552#else
553 return false;
554#endif
555}
556
Mugdha Lakhani5f8de7cc2020-03-10 20:43:36557void Shell::NavigationStateChanged(WebContents* source,
558 InvalidateTypes changed_flags) {
559 if (changed_flags & INVALIDATE_TYPE_URL)
danakjde3e2a02020-05-12 16:51:20560 g_platform->SetAddressBarURL(this, source->GetVisibleURL());
[email protected]e99ca5112011-09-26 17:22:54561}
562
mathiash72a5e462014-11-19 08:18:50563JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
564 WebContents* source) {
mkwst6efe7f2e62014-10-08 15:09:01565 if (!dialog_manager_) {
danakjaf29c6072020-03-31 16:25:01566 if (switches::IsRunWebTestsSwitchPresent())
567 dialog_manager_ = std::make_unique<WebTestJavaScriptDialogManager>();
568 else
569 dialog_manager_ = std::make_unique<ShellJavaScriptDialogManager>();
mkwst6efe7f2e62014-10-08 15:09:01570 }
[email protected]71a88bb2013-02-01 22:05:15571 return dialog_manager_.get();
[email protected]f2210022012-03-29 00:36:08572}
573
dcheng6003e0b2016-04-09 18:42:34574std::unique_ptr<BluetoothChooser> Shell::RunBluetoothChooser(
jyasskin93649a52016-02-17 19:57:02575 RenderFrameHost* frame,
576 const BluetoothChooser::EventHandler& event_handler) {
Gyuyoung Kim26c7bc92020-04-29 00:53:00577 WebTestControlHost* web_test_control_host = WebTestControlHost::Get();
578 if (web_test_control_host && switches::IsRunWebTestsSwitchPresent())
579 return web_test_control_host->RunBluetoothChooser(frame, event_handler);
jyasskin8057c002015-09-10 19:09:53580 return nullptr;
581}
582
Jun Cai149002e2019-05-09 23:13:07583std::unique_ptr<BluetoothScanningPrompt> Shell::ShowBluetoothScanningPrompt(
584 RenderFrameHost* frame,
585 const BluetoothScanningPrompt::EventHandler& event_handler) {
586 return std::make_unique<FakeBluetoothScanningPrompt>(event_handler);
587}
588
danakjde3e2a02020-05-12 16:51:20589#if defined(OS_MACOSX)
590bool Shell::HandleKeyboardEvent(WebContents* source,
591 const NativeWebKeyboardEvent& event) {
592 return g_platform->HandleKeyboardEvent(this, source, event);
593}
594#endif
595
avia90ae4e2016-11-11 20:49:33596bool Shell::DidAddMessageToConsole(WebContents* source,
Lowell Manners1de5242e2019-04-25 10:18:46597 blink::mojom::ConsoleMessageLevel log_level,
avia90ae4e2016-11-11 20:49:33598 const base::string16& message,
599 int32_t line_no,
600 const base::string16& source_id) {
Kent Tamuracd3ebc42018-05-16 06:44:22601 return switches::IsRunWebTestsSwitchPresent();
[email protected]efb5f572012-01-29 10:57:33602}
603
Lucas Furukawa Gadani06548fb2019-01-15 05:01:25604void Shell::PortalWebContentsCreated(WebContents* portal_web_contents) {
605 if (switches::IsRunWebTestsSwitchPresent())
606 SecondaryTestWindowObserver::CreateForWebContents(portal_web_contents);
607}
608
Lukasz Anforowicz52b93722018-06-20 16:11:39609void Shell::RendererUnresponsive(
610 WebContents* source,
611 RenderWidgetHost* render_widget_host,
612 base::RepeatingClosure hang_monitor_restarter) {
Gyuyoung Kim26c7bc92020-04-29 00:53:00613 WebTestControlHost* web_test_control_host = WebTestControlHost::Get();
614 if (web_test_control_host && switches::IsRunWebTestsSwitchPresent())
615 web_test_control_host->RendererUnresponsive();
[email protected]5bf68f22012-08-31 07:38:10616}
617
[email protected]233567d2013-02-27 20:22:02618void Shell::ActivateContents(WebContents* contents) {
danakj674bf1c02020-05-01 18:37:51619#if !defined(OS_MACOSX)
620 contents->Focus();
621#else
622 // Mac headless mode is quite different than other platforms. Normally
623 // focusing the WebContents would cause the OS to focus the window. Because
624 // headless mac doesn't actually have system windows, we can't go down the
625 // normal path and have to fake it out in the browser process.
danakjde3e2a02020-05-12 16:51:20626 g_platform->ActivateContents(this, contents);
danakj674bf1c02020-05-01 18:37:51627#endif
[email protected]233567d2013-02-27 20:22:02628}
629
Kevin McNee7422bc42020-02-20 18:49:55630std::unique_ptr<WebContents> Shell::ActivatePortalWebContents(
631 WebContents* predecessor_contents,
632 std::unique_ptr<WebContents> portal_contents) {
633 DCHECK_EQ(predecessor_contents, web_contents_.get());
634 portal_contents->SetDelegate(this);
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33635 web_contents_->SetDelegate(nullptr);
Adithya Srinivasan5d50d1e2019-10-09 00:27:48636 for (auto* shell_devtools_bindings :
Kevin McNee7422bc42020-02-20 18:49:55637 ShellDevToolsBindings::GetInstancesForWebContents(
638 predecessor_contents)) {
639 shell_devtools_bindings->UpdateInspectedWebContents(portal_contents.get());
Adithya Srinivasan5d50d1e2019-10-09 00:27:48640 }
Kevin McNee7422bc42020-02-20 18:49:55641 std::swap(web_contents_, portal_contents);
danakjde3e2a02020-05-12 16:51:20642 g_platform->SetContents(this);
643 g_platform->SetAddressBarURL(this, web_contents_->GetVisibleURL());
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33644 LoadingStateChanged(web_contents_.get(), true);
Kevin McNee7422bc42020-02-20 18:49:55645 return portal_contents;
Lucas Furukawa Gadanic5c0cd02018-10-04 20:32:33646}
647
Lukasz Anforowicz82a5ca92019-10-24 18:45:37648bool Shell::ShouldAllowRunningInsecureContent(WebContents* web_contents,
649 bool allowed_per_prefs,
650 const url::Origin& origin,
651 const GURL& resource_url) {
carloskd9d97942017-02-16 08:58:09652 bool allowed_by_test = false;
Gyuyoung Kim26c7bc92020-04-29 00:53:00653 WebTestControlHost* web_test_control_host = WebTestControlHost::Get();
654 if (web_test_control_host && switches::IsRunWebTestsSwitchPresent()) {
carloskd9d97942017-02-16 08:58:09655 const base::DictionaryValue& test_flags =
Gyuyoung Kim26c7bc92020-04-29 00:53:00656 web_test_control_host->accumulated_web_test_runtime_flags_changes();
carloskd9d97942017-02-16 08:58:09657 test_flags.GetBoolean("running_insecure_content_allowed", &allowed_by_test);
658 }
659
660 return allowed_per_prefs || allowed_by_test;
661}
662
Becca Hughes112832e2019-06-11 17:19:02663PictureInPictureResult Shell::EnterPictureInPicture(
Lukasz Anforowicz82a5ca92019-10-24 18:45:37664 WebContents* web_contents,
Becca Hughes112832e2019-06-11 17:19:02665 const viz::SurfaceId& surface_id,
666 const gfx::Size& natural_size) {
667 // During tests, returning success to pretend the window was created and allow
668 // tests to run accordingly.
669 if (!switches::IsRunWebTestsSwitchPresent())
670 return PictureInPictureResult::kNotSupported;
Becca Hughes112832e2019-06-11 17:19:02671 return PictureInPictureResult::kSuccess;
Mounir Lamouri11e9ef432018-05-22 03:10:16672}
673
Bo Liu300c6052018-06-12 04:46:07674bool Shell::ShouldResumeRequestsForCreatedWindow() {
675 return !delay_popup_contents_delegate_for_testing_;
676}
677
pdrcab84ee2015-03-13 21:47:04678gfx::Size Shell::GetShellDefaultSize() {
679 static gfx::Size default_shell_size;
680 if (!default_shell_size.IsEmpty())
681 return default_shell_size;
682 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
683 if (command_line->HasSwitch(switches::kContentShellHostWindowSize)) {
684 const std::string size_str = command_line->GetSwitchValueASCII(
685 switches::kContentShellHostWindowSize);
686 int width, height;
687 CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
688 default_shell_size = gfx::Size(width, height);
689 } else {
690 default_shell_size = gfx::Size(
691 kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
692 }
693 return default_shell_size;
694}
695
danakjde3e2a02020-05-12 16:51:20696#if defined(OS_ANDROID)
697void Shell::LoadProgressChanged(double progress) {
698 g_platform->LoadProgressChanged(this, progress);
699}
700#endif
701
Avi Drissman93002212017-09-27 03:20:52702void Shell::TitleWasSet(NavigationEntry* entry) {
[email protected]1ef02d242013-10-07 16:18:53703 if (entry)
danakjde3e2a02020-05-12 16:51:20704 g_platform->SetTitle(this, entry->GetTitle());
[email protected]aecc085b2012-06-01 18:15:53705}
706
[email protected]7fff43e2013-05-21 20:21:10707void Shell::OnDevToolsWebContentsDestroyed() {
708 devtools_observer_.reset();
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28709 devtools_frontend_ = nullptr;
[email protected]7fff43e2013-05-21 20:21:10710}
711
[email protected]9fbd3f862011-09-20 23:31:34712} // namespace content