1 /*
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
31
32 #include <algorithm>
33 #include <memory>
34 #include <utility>
35
36 #include "base/auto_reset.h"
37 #include "base/command_line.h"
38 #include "base/memory/scoped_refptr.h"
39 #include "base/metrics/histogram_macros.h"
40 #include "base/time/time.h"
41 #include "build/build_config.h"
42 #include "cc/layers/picture_layer.h"
43 #include "media/base/media_switches.h"
44 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
45 #include "third_party/blink/public/common/features.h"
46 #include "third_party/blink/public/common/input/web_input_event.h"
47 #include "third_party/blink/public/common/input/web_menu_source_type.h"
48 #include "third_party/blink/public/common/page/page_zoom.h"
49 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
50 #include "third_party/blink/public/common/switches.h"
51 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
52 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
53 #include "third_party/blink/public/platform/interface_registry.h"
54 #include "third_party/blink/public/platform/platform.h"
55 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
56 #include "third_party/blink/public/platform/web_media_player.h"
57 #include "third_party/blink/public/platform/web_network_state_notifier.h"
58 #include "third_party/blink/public/platform/web_runtime_features.h"
59 #include "third_party/blink/public/platform/web_text_input_info.h"
60 #include "third_party/blink/public/platform/web_url_request.h"
61 #include "third_party/blink/public/platform/web_vector.h"
62 #include "third_party/blink/public/web/web_autofill_client.h"
63 #include "third_party/blink/public/web/web_console_message.h"
64 #include "third_party/blink/public/web/web_element.h"
65 #include "third_party/blink/public/web/web_frame.h"
66 #include "third_party/blink/public/web/web_hit_test_result.h"
67 #include "third_party/blink/public/web/web_input_element.h"
68 #include "third_party/blink/public/web/web_local_frame_client.h"
69 #include "third_party/blink/public/web/web_meaningful_layout.h"
70 #include "third_party/blink/public/web/web_node.h"
71 #include "third_party/blink/public/web/web_plugin.h"
72 #include "third_party/blink/public/web/web_range.h"
73 #include "third_party/blink/public/web/web_render_theme.h"
74 #include "third_party/blink/public/web/web_view_client.h"
75 #include "third_party/blink/public/web/web_widget_client.h"
76 #include "third_party/blink/public/web/web_window_features.h"
77 #include "third_party/blink/renderer/core/clipboard/data_object.h"
78 #include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
79 #include "third_party/blink/renderer/core/core_initializer.h"
80 #include "third_party/blink/renderer/core/css_value_keywords.h"
81 #include "third_party/blink/renderer/core/dom/context_features_client_impl.h"
82 #include "third_party/blink/renderer/core/dom/document.h"
83 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
84 #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
85 #include "third_party/blink/renderer/core/dom/text.h"
86 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
87 #include "third_party/blink/renderer/core/editing/editor.h"
88 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
89 #include "third_party/blink/renderer/core/editing/frame_selection.h"
90 #include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
91 #include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
92 #include "third_party/blink/renderer/core/editing/selection_template.h"
93 #include "third_party/blink/renderer/core/editing/serializers/html_interchange.h"
94 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
95 #include "third_party/blink/renderer/core/events/current_input_event.h"
96 #include "third_party/blink/renderer/core/events/keyboard_event.h"
97 #include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
98 #include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
99 #include "third_party/blink/renderer/core/events/wheel_event.h"
100 #include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
101 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
102 #include "third_party/blink/renderer/core/exported/web_settings_impl.h"
103 #include "third_party/blink/renderer/core/frame/browser_controls.h"
104 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
105 #include "third_party/blink/renderer/core/frame/fullscreen_controller.h"
106 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
107 #include "third_party/blink/renderer/core/frame/local_frame.h"
108 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
109 #include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
110 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
111 #include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
112 #include "third_party/blink/renderer/core/frame/remote_frame.h"
113 #include "third_party/blink/renderer/core/frame/resize_viewport_anchor.h"
114 #include "third_party/blink/renderer/core/frame/rotation_viewport_anchor.h"
115 #include "third_party/blink/renderer/core/frame/settings.h"
116 #include "third_party/blink/renderer/core/frame/viewport_data.h"
117 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
118 #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
119 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
120 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
121 #include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
122 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
123 #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
124 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
125 #include "third_party/blink/renderer/core/html/plugin_document.h"
126 #include "third_party/blink/renderer/core/html_names.h"
127 #include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
128 #include "third_party/blink/renderer/core/input/event_handler.h"
129 #include "third_party/blink/renderer/core/input/touch_action_util.h"
130 #include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h"
131 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
132 #include "third_party/blink/renderer/core/layout/layout_view.h"
133 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
134 #include "third_party/blink/renderer/core/loader/document_loader.h"
135 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
136 #include "third_party/blink/renderer/core/loader/frame_loader.h"
137 #include "third_party/blink/renderer/core/loader/interactive_detector.h"
138 #include "third_party/blink/renderer/core/loader/prerenderer_client.h"
139 #include "third_party/blink/renderer/core/page/chrome_client_impl.h"
140 #include "third_party/blink/renderer/core/page/context_menu_controller.h"
141 #include "third_party/blink/renderer/core/page/context_menu_provider.h"
142 #include "third_party/blink/renderer/core/page/focus_controller.h"
143 #include "third_party/blink/renderer/core/page/frame_tree.h"
144 #include "third_party/blink/renderer/core/page/link_highlight.h"
145 #include "third_party/blink/renderer/core/page/page.h"
146 #include "third_party/blink/renderer/core/page/page_popup_client.h"
147 #include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
148 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
149 #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
150 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
151 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
152 #include "third_party/blink/renderer/core/paint/paint_timing.h"
153 #include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
154 #include "third_party/blink/renderer/core/probe/core_probes.h"
155 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
156 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
157 #include "third_party/blink/renderer/core/timing/window_performance.h"
158 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
159 #include "third_party/blink/renderer/platform/graphics/image.h"
160 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
161 #include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
162 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
163 #include "third_party/blink/renderer/platform/instrumentation/histogram.h"
164 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
165 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
166 #include "third_party/blink/renderer/platform/keyboard_codes.h"
167 #include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
168 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
169 #include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h"
170 #include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
171 #include "third_party/blink/renderer/platform/widget/widget_base.h"
172 #include "third_party/icu/source/common/unicode/uscript.h"
173 #include "ui/base/ui_base_features.h"
174 #include "ui/gfx/skia_util.h"
175
176 #if defined(OS_ANDROID)
177 #include "components/viz/common/features.h"
178 #endif
179
180 #if !defined(OS_MAC)
181 #include "skia/ext/legacy_display_globals.h"
182 #include "third_party/blink/public/platform/web_font_render_style.h"
183 #include "ui/gfx/font_render_params.h"
184 #endif
185
186 #if defined(OS_WIN)
187 #include "third_party/blink/public/web/win/web_font_rendering.h"
188 #endif
189
190 // Get rid of WTF's pow define so we can use std::pow.
191 #undef pow
192 #include <cmath> // for std::pow
193
194 // The following constants control parameters for automated scaling of webpages
195 // (such as due to a double tap gesture or find in page etc.). These are
196 // experimentally determined.
197 static const int touchPointPadding = 32;
198 static const int nonUserInitiatedPointPadding = 11;
199 static const float minScaleDifference = 0.01f;
200 static const float doubleTapZoomContentDefaultMargin = 5;
201 static const float doubleTapZoomContentMinimumMargin = 2;
202 static constexpr base::TimeDelta kDoubleTapZoomAnimationDuration =
203 base::TimeDelta::FromMilliseconds(250);
204 static const float doubleTapZoomAlreadyLegibleRatio = 1.2f;
205
206 static constexpr base::TimeDelta kFindInPageAnimationDuration;
207
208 // Constants for viewport anchoring on resize.
209 static const float viewportAnchorCoordX = 0.5f;
210 static const float viewportAnchorCoordY = 0;
211
212 // Constants for zooming in on a focused text field.
213 static constexpr base::TimeDelta kScrollAndScaleAnimationDuration =
214 base::TimeDelta::FromMicroseconds(200);
215 static const int minReadableCaretHeight = 16;
216 static const int minReadableCaretHeightForTextArea = 13;
217 static const float minScaleChangeToTriggerZoom = 1.5f;
218 static const float leftBoxRatio = 0.3f;
219 static const int caretPadding = 10;
220
221 namespace blink {
222
223 // Historically, these values came from Webkit in
224 // WebKitLegacy/mac/WebView/WebView.mm (named MinimumZoomMultiplier and
225 // MaximumZoomMultiplier there).
226 const double WebView::kMinTextSizeMultiplier = 0.5;
227 const double WebView::kMaxTextSizeMultiplier = 3.0;
228
229 // static
AllInstances()230 HashSet<WebViewImpl*>& WebViewImpl::AllInstances() {
231 DEFINE_STATIC_LOCAL(HashSet<WebViewImpl*>, all_instances, ());
232 return all_instances;
233 }
234
235 static bool g_should_use_external_popup_menus = false;
236
SetUseExternalPopupMenus(bool use_external_popup_menus)237 void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) {
238 g_should_use_external_popup_menus = use_external_popup_menus;
239 }
240
UseExternalPopupMenus()241 bool WebViewImpl::UseExternalPopupMenus() {
242 return g_should_use_external_popup_menus;
243 }
244
245 namespace {
246
247 class EmptyEventListener final : public NativeEventListener {
248 public:
Invoke(ExecutionContext * execution_context,Event *)249 void Invoke(ExecutionContext* execution_context, Event*) override {}
250 };
251
252 typedef void (*SetFontFamilyWrapper)(blink::WebSettings*,
253 const base::string16&,
254 UScriptCode);
255
SetStandardFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)256 void SetStandardFontFamilyWrapper(WebSettings* settings,
257 const base::string16& font,
258 UScriptCode script) {
259 settings->SetStandardFontFamily(WebString::FromUTF16(font), script);
260 }
261
SetFixedFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)262 void SetFixedFontFamilyWrapper(WebSettings* settings,
263 const base::string16& font,
264 UScriptCode script) {
265 settings->SetFixedFontFamily(WebString::FromUTF16(font), script);
266 }
267
SetSerifFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)268 void SetSerifFontFamilyWrapper(WebSettings* settings,
269 const base::string16& font,
270 UScriptCode script) {
271 settings->SetSerifFontFamily(WebString::FromUTF16(font), script);
272 }
273
SetSansSerifFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)274 void SetSansSerifFontFamilyWrapper(WebSettings* settings,
275 const base::string16& font,
276 UScriptCode script) {
277 settings->SetSansSerifFontFamily(WebString::FromUTF16(font), script);
278 }
279
SetCursiveFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)280 void SetCursiveFontFamilyWrapper(WebSettings* settings,
281 const base::string16& font,
282 UScriptCode script) {
283 settings->SetCursiveFontFamily(WebString::FromUTF16(font), script);
284 }
285
SetFantasyFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)286 void SetFantasyFontFamilyWrapper(WebSettings* settings,
287 const base::string16& font,
288 UScriptCode script) {
289 settings->SetFantasyFontFamily(WebString::FromUTF16(font), script);
290 }
291
SetPictographFontFamilyWrapper(WebSettings * settings,const base::string16 & font,UScriptCode script)292 void SetPictographFontFamilyWrapper(WebSettings* settings,
293 const base::string16& font,
294 UScriptCode script) {
295 settings->SetPictographFontFamily(WebString::FromUTF16(font), script);
296 }
297
298 // If |scriptCode| is a member of a family of "similar" script codes, returns
299 // the script code in that family that is used by WebKit for font selection
300 // purposes. For example, USCRIPT_KATAKANA_OR_HIRAGANA and USCRIPT_JAPANESE are
301 // considered equivalent for the purposes of font selection. WebKit uses the
302 // script code USCRIPT_KATAKANA_OR_HIRAGANA. So, if |scriptCode| is
303 // USCRIPT_JAPANESE, the function returns USCRIPT_KATAKANA_OR_HIRAGANA. WebKit
304 // uses different scripts than the ones in Chrome pref names because the version
305 // of ICU included on certain ports does not have some of the newer scripts. If
306 // |scriptCode| is not a member of such a family, returns |scriptCode|.
GetScriptForWebSettings(UScriptCode scriptCode)307 UScriptCode GetScriptForWebSettings(UScriptCode scriptCode) {
308 switch (scriptCode) {
309 case USCRIPT_HIRAGANA:
310 case USCRIPT_KATAKANA:
311 case USCRIPT_JAPANESE:
312 return USCRIPT_KATAKANA_OR_HIRAGANA;
313 case USCRIPT_KOREAN:
314 return USCRIPT_HANGUL;
315 default:
316 return scriptCode;
317 }
318 }
319
ApplyFontsFromMap(const web_pref::ScriptFontFamilyMap & map,SetFontFamilyWrapper setter,WebSettings * settings)320 void ApplyFontsFromMap(const web_pref::ScriptFontFamilyMap& map,
321 SetFontFamilyWrapper setter,
322 WebSettings* settings) {
323 for (auto& it : map) {
324 int32_t script = u_getPropertyValueEnum(UCHAR_SCRIPT, (it.first).c_str());
325 if (script >= 0 && script < USCRIPT_CODE_LIMIT) {
326 UScriptCode code = static_cast<UScriptCode>(script);
327 (*setter)(settings, it.second, GetScriptForWebSettings(code));
328 }
329 }
330 }
331
ApplyCommandLineToSettings(WebSettings * settings)332 void ApplyCommandLineToSettings(WebSettings* settings) {
333 const base::CommandLine& command_line =
334 *base::CommandLine::ForCurrentProcess();
335
336 WebSettings::SelectionStrategyType selection_strategy;
337 if (command_line.GetSwitchValueASCII(switches::kTouchTextSelectionStrategy) ==
338 "direction")
339 selection_strategy = WebSettings::SelectionStrategyType::kDirection;
340 else
341 selection_strategy = WebSettings::SelectionStrategyType::kCharacter;
342 settings->SetSelectionStrategy(selection_strategy);
343
344 WebString passive_listeners_default = WebString::FromUTF8(
345 command_line.GetSwitchValueASCII(switches::kPassiveListenersDefault));
346 if (!passive_listeners_default.IsEmpty()) {
347 WebSettings::PassiveEventListenerDefault passive_default =
348 WebSettings::PassiveEventListenerDefault::kFalse;
349 if (passive_listeners_default == "true")
350 passive_default = WebSettings::PassiveEventListenerDefault::kTrue;
351 else if (passive_listeners_default == "forcealltrue")
352 passive_default = WebSettings::PassiveEventListenerDefault::kForceAllTrue;
353 settings->SetPassiveEventListenerDefault(passive_default);
354 }
355
356 WebString network_quiet_timeout = WebString::FromUTF8(
357 command_line.GetSwitchValueASCII(switches::kNetworkQuietTimeout));
358 if (!network_quiet_timeout.IsEmpty()) {
359 bool ok;
360 double network_quiet_timeout_seconds =
361 String(network_quiet_timeout).ToDouble(&ok);
362 if (ok)
363 settings->SetNetworkQuietTimeout(network_quiet_timeout_seconds);
364 }
365
366 if (command_line.HasSwitch(switches::kBlinkSettings)) {
367 Vector<String> blink_settings;
368 String command_line_settings =
369 command_line.GetSwitchValueASCII(switches::kBlinkSettings).c_str();
370 command_line_settings.Split(",", blink_settings);
371 for (const String& setting : blink_settings) {
372 wtf_size_t pos = setting.find('=');
373 settings->SetFromStrings(
374 WebString(setting.Substring(0, pos)),
375 WebString(pos == kNotFound ? "" : setting.Substring(pos + 1)));
376 }
377 }
378 }
379
GetVideoSurfaceLayerMode()380 WebMediaPlayer::SurfaceLayerMode GetVideoSurfaceLayerMode() {
381 #if defined(OS_ANDROID)
382 if (base::FeatureList::IsEnabled(media::kDisableSurfaceLayerForVideo) &&
383 !::features::IsUsingVizForWebView())
384 return WebMediaPlayer::SurfaceLayerMode::kNever;
385 #endif // OS_ANDROID
386
387 return WebMediaPlayer::SurfaceLayerMode::kAlways;
388 }
389
NavigationPolicyToDisposition(NavigationPolicy policy)390 ui::mojom::blink::WindowOpenDisposition NavigationPolicyToDisposition(
391 NavigationPolicy policy) {
392 switch (policy) {
393 case kNavigationPolicyDownload:
394 return ui::mojom::blink::WindowOpenDisposition::SAVE_TO_DISK;
395 case kNavigationPolicyCurrentTab:
396 return ui::mojom::blink::WindowOpenDisposition::CURRENT_TAB;
397 case kNavigationPolicyNewBackgroundTab:
398 return ui::mojom::blink::WindowOpenDisposition::NEW_BACKGROUND_TAB;
399 case kNavigationPolicyNewForegroundTab:
400 return ui::mojom::blink::WindowOpenDisposition::NEW_FOREGROUND_TAB;
401 case kNavigationPolicyNewWindow:
402 return ui::mojom::blink::WindowOpenDisposition::NEW_WINDOW;
403 case kNavigationPolicyNewPopup:
404 return ui::mojom::blink::WindowOpenDisposition::NEW_POPUP;
405 }
406 NOTREACHED() << "Unexpected NavigationPolicy";
407 return ui::mojom::blink::WindowOpenDisposition::IGNORE_ACTION;
408 }
409
410 #if !defined(OS_MAC) && !defined(OS_WIN)
RendererPreferencesToSkiaHinting(const blink::RendererPreferences & prefs)411 SkFontHinting RendererPreferencesToSkiaHinting(
412 const blink::RendererPreferences& prefs) {
413 #if defined(OS_LINUX) || defined(OS_BSD)
414 if (!prefs.should_antialias_text) {
415 // When anti-aliasing is off, GTK maps all non-zero hinting settings to
416 // 'Normal' hinting so we do the same. Otherwise, folks who have 'Slight'
417 // hinting selected will see readable text in everything expect Chromium.
418 switch (prefs.hinting) {
419 case gfx::FontRenderParams::HINTING_NONE:
420 return SkFontHinting::kNone;
421 case gfx::FontRenderParams::HINTING_SLIGHT:
422 case gfx::FontRenderParams::HINTING_MEDIUM:
423 case gfx::FontRenderParams::HINTING_FULL:
424 return SkFontHinting::kNormal;
425 default:
426 NOTREACHED();
427 return SkFontHinting::kNormal;
428 }
429 }
430 #endif
431
432 switch (prefs.hinting) {
433 case gfx::FontRenderParams::HINTING_NONE:
434 return SkFontHinting::kNone;
435 case gfx::FontRenderParams::HINTING_SLIGHT:
436 return SkFontHinting::kSlight;
437 case gfx::FontRenderParams::HINTING_MEDIUM:
438 return SkFontHinting::kNormal;
439 case gfx::FontRenderParams::HINTING_FULL:
440 return SkFontHinting::kFull;
441 default:
442 NOTREACHED();
443 return SkFontHinting::kNormal;
444 }
445 }
446 #endif // OS_MAC
447
448 } // namespace
449
450 // WebView ----------------------------------------------------------------
451
Create(WebViewClient * client,bool is_hidden,bool is_inside_portal,bool compositing_enabled,WebView * opener,CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase> page_handle,scheduler::WebAgentGroupScheduler & agent_group_scheduler)452 WebView* WebView::Create(
453 WebViewClient* client,
454 bool is_hidden,
455 bool is_inside_portal,
456 bool compositing_enabled,
457 WebView* opener,
458 CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase>
459 page_handle,
460 scheduler::WebAgentGroupScheduler& agent_group_scheduler) {
461 return WebViewImpl::Create(
462 client,
463 is_hidden ? mojom::blink::PageVisibilityState::kHidden
464 : mojom::blink::PageVisibilityState::kVisible,
465 is_inside_portal, compositing_enabled, static_cast<WebViewImpl*>(opener),
466 std::move(page_handle), agent_group_scheduler);
467 }
468
Create(WebViewClient * client,mojom::blink::PageVisibilityState visibility,bool is_inside_portal,bool compositing_enabled,WebViewImpl * opener,mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,blink::scheduler::WebAgentGroupScheduler & agent_group_scheduler)469 WebViewImpl* WebViewImpl::Create(
470 WebViewClient* client,
471 mojom::blink::PageVisibilityState visibility,
472 bool is_inside_portal,
473 bool compositing_enabled,
474 WebViewImpl* opener,
475 mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
476 blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler) {
477 // Take a self-reference for WebViewImpl that is released by calling Close(),
478 // then return a raw pointer to the caller.
479 auto web_view = base::AdoptRef(
480 new WebViewImpl(client, visibility, is_inside_portal, compositing_enabled,
481 opener, std::move(page_handle), agent_group_scheduler));
482 web_view->AddRef();
483 return web_view.get();
484 }
485
UpdateVisitedLinkState(uint64_t link_hash)486 void WebView::UpdateVisitedLinkState(uint64_t link_hash) {
487 Page::VisitedStateChanged(link_hash);
488 }
489
ResetVisitedLinkState(bool invalidate_visited_link_hashes)490 void WebView::ResetVisitedLinkState(bool invalidate_visited_link_hashes) {
491 Page::AllVisitedStateChanged(invalidate_visited_link_hashes);
492 }
493
SetPrerendererClient(WebPrerendererClient * prerenderer_client)494 void WebViewImpl::SetPrerendererClient(
495 WebPrerendererClient* prerenderer_client) {
496 DCHECK(page_);
497 ProvidePrerendererClientTo(*page_, MakeGarbageCollected<PrerendererClient>(
498 *page_, prerenderer_client));
499 }
500
CloseWindowSoon()501 void WebViewImpl::CloseWindowSoon() {
502 // Ask the RenderViewHost with a local main frame to initiate close. We
503 // could be called from deep in Javascript. If we ask the RenderViewHost to
504 // close now, the window could be closed before the JS finishes executing,
505 // thanks to nested message loops running and handling the resulting
506 // DestroyView IPC. So instead, post a message back to the message loop, which
507 // won't run until the JS is complete, and then the
508 // RouteCloseEvent/RequestClose request can be sent.
509 GetPage()
510 ->GetPageScheduler()
511 ->GetAgentGroupScheduler()
512 .DefaultTaskRunner()
513 ->PostTask(FROM_HERE, WTF::Bind(&WebViewImpl::DoDeferredCloseWindowSoon,
514 weak_ptr_factory_.GetWeakPtr()));
515 }
516
DoDeferredCloseWindowSoon()517 void WebViewImpl::DoDeferredCloseWindowSoon() {
518 // Have the browser process a close request. We should have either a
519 // |local_main_frame_host_remote_| or |remote_main_frame_host_remote_|.
520 // This method will not execute if Close has been called as WeakPtrs
521 // will be invalidated in Close.
522 if (GetPage()->MainFrame()->IsLocalFrame()) {
523 DCHECK(local_main_frame_host_remote_);
524 local_main_frame_host_remote_->RequestClose();
525 } else {
526 DCHECK(remote_main_frame_host_remote_);
527 remote_main_frame_host_remote_->RouteCloseEvent();
528 }
529 }
530
WebViewImpl(WebViewClient * client,mojom::blink::PageVisibilityState visibility,bool is_inside_portal,bool does_composite,WebViewImpl * opener,mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,blink::scheduler::WebAgentGroupScheduler & agent_group_scheduler)531 WebViewImpl::WebViewImpl(
532 WebViewClient* client,
533 mojom::blink::PageVisibilityState visibility,
534 bool is_inside_portal,
535 bool does_composite,
536 WebViewImpl* opener,
537 mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
538 blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler)
539 : web_view_client_(client),
540 chrome_client_(MakeGarbageCollected<ChromeClientImpl>(this)),
541 minimum_zoom_level_(PageZoomFactorToZoomLevel(kMinimumPageZoomFactor)),
542 maximum_zoom_level_(PageZoomFactorToZoomLevel(kMaximumPageZoomFactor)),
543 does_composite_(does_composite),
544 fullscreen_controller_(std::make_unique<FullscreenController>(this)),
545 receiver_(this,
546 std::move(page_handle),
547 agent_group_scheduler.DefaultTaskRunner()) {
548 if (!web_view_client_)
549 DCHECK(!does_composite_);
550 Page::PageClients page_clients;
551 page_clients.chrome_client = chrome_client_.Get();
552 page_ =
553 Page::CreateOrdinary(page_clients, opener ? opener->GetPage() : nullptr,
554 agent_group_scheduler);
555 CoreInitializer::GetInstance().ProvideModulesToPage(*page_, web_view_client_);
556
557 SetVisibilityState(visibility, /*is_initial_state=*/true);
558
559 // We pass this state to Page, but it's only used by the main frame in the
560 // page.
561 SetInsidePortal(is_inside_portal);
562
563 // When not compositing, keep the Page in the loop so that it will paint all
564 // content into the root layer, as multiple layers can only be used when
565 // compositing them together later.
566 if (does_composite_)
567 page_->GetSettings().SetAcceleratedCompositingEnabled(true);
568
569 dev_tools_emulator_ = MakeGarbageCollected<DevToolsEmulator>(this);
570
571 AllInstances().insert(this);
572
573 resize_viewport_anchor_ = MakeGarbageCollected<ResizeViewportAnchor>(*page_);
574 }
575
~WebViewImpl()576 WebViewImpl::~WebViewImpl() {
577 DCHECK(!page_);
578 }
579
MainFrameDevToolsAgentImpl()580 WebDevToolsAgentImpl* WebViewImpl::MainFrameDevToolsAgentImpl() {
581 WebLocalFrameImpl* main_frame = MainFrameImpl();
582 return main_frame ? main_frame->DevToolsAgentImpl() : nullptr;
583 }
584
SetTabKeyCyclesThroughElements(bool value)585 void WebViewImpl::SetTabKeyCyclesThroughElements(bool value) {
586 if (page_)
587 page_->SetTabKeyCyclesThroughElements(value);
588 }
589
StartPageScaleAnimation(const IntPoint & target_position,bool use_anchor,float new_scale,base::TimeDelta duration)590 bool WebViewImpl::StartPageScaleAnimation(const IntPoint& target_position,
591 bool use_anchor,
592 float new_scale,
593 base::TimeDelta duration) {
594 // PageScaleFactor is a property of the main frame only, and only exists when
595 // compositing.
596 DCHECK(MainFrameImpl());
597 DCHECK(does_composite_);
598
599 VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
600 gfx::Point clamped_point = target_position;
601 if (!use_anchor) {
602 clamped_point =
603 visual_viewport.ClampDocumentOffsetAtScale(target_position, new_scale);
604 if (duration.is_zero()) {
605 SetPageScaleFactor(new_scale);
606
607 LocalFrameView* view = MainFrameImpl()->GetFrameView();
608 if (view && view->GetScrollableArea()) {
609 view->GetScrollableArea()->SetScrollOffset(
610 ScrollOffset(clamped_point.x(), clamped_point.y()),
611 mojom::blink::ScrollType::kProgrammatic);
612 }
613
614 return false;
615 }
616 }
617 if (use_anchor && new_scale == PageScaleFactor())
618 return false;
619
620 if (enable_fake_page_scale_animation_for_testing_) {
621 fake_page_scale_animation_target_position_ = target_position;
622 fake_page_scale_animation_use_anchor_ = use_anchor;
623 fake_page_scale_animation_page_scale_factor_ = new_scale;
624 } else {
625 MainFrameImpl()->FrameWidgetImpl()->StartPageScaleAnimation(
626 static_cast<gfx::Vector2d>(target_position), use_anchor, new_scale,
627 duration);
628 }
629 return true;
630 }
631
EnableFakePageScaleAnimationForTesting(bool enable)632 void WebViewImpl::EnableFakePageScaleAnimationForTesting(bool enable) {
633 enable_fake_page_scale_animation_for_testing_ = enable;
634 fake_page_scale_animation_target_position_ = IntPoint();
635 fake_page_scale_animation_use_anchor_ = false;
636 fake_page_scale_animation_page_scale_factor_ = 0;
637 }
638
AcceptLanguagesChanged()639 void WebViewImpl::AcceptLanguagesChanged() {
640 if (web_view_client_)
641 FontCache::AcceptLanguagesChanged(web_view_client_->AcceptLanguages());
642
643 if (!GetPage())
644 return;
645
646 GetPage()->AcceptLanguagesChanged();
647 }
648
WidenRectWithinPageBounds(const WebRect & source,int target_margin,int minimum_margin)649 WebRect WebViewImpl::WidenRectWithinPageBounds(const WebRect& source,
650 int target_margin,
651 int minimum_margin) {
652 // Caller should guarantee that the main frame exists and is local.
653 DCHECK(MainFrame());
654 DCHECK(MainFrame()->IsWebLocalFrame());
655 WebSize max_size = MainFrame()->ToWebLocalFrame()->DocumentSize();
656 IntSize scroll_offset = MainFrame()->ToWebLocalFrame()->GetScrollOffset();
657
658 int left_margin = target_margin;
659 int right_margin = target_margin;
660
661 const int absolute_source_x = source.x + scroll_offset.Width();
662 if (left_margin > absolute_source_x) {
663 left_margin = absolute_source_x;
664 right_margin = std::max(left_margin, minimum_margin);
665 }
666
667 const int maximum_right_margin =
668 max_size.width - (source.width + absolute_source_x);
669 if (right_margin > maximum_right_margin) {
670 right_margin = maximum_right_margin;
671 left_margin = std::min(left_margin, std::max(right_margin, minimum_margin));
672 }
673
674 const int new_width = source.width + left_margin + right_margin;
675 const int new_x = source.x - left_margin;
676
677 DCHECK_GE(new_width, 0);
678 DCHECK_LE(scroll_offset.Width() + new_x + new_width, max_size.width);
679
680 return WebRect(new_x, source.y, new_width, source.height);
681 }
682
MaximumLegiblePageScale() const683 float WebViewImpl::MaximumLegiblePageScale() const {
684 // Pages should be as legible as on desktop when at dpi scale, so no
685 // need to zoom in further when automatically determining zoom level
686 // (after double tap, find in page, etc), though the user should still
687 // be allowed to manually pinch zoom in further if they desire.
688 if (GetPage()) {
689 return maximum_legible_scale_ *
690 GetPage()->GetSettings().GetAccessibilityFontScaleFactor();
691 }
692 return maximum_legible_scale_;
693 }
694
ComputeScaleAndScrollForBlockRect(const gfx::Point & hit_point_in_root_frame,const WebRect & block_rect_in_root_frame,float padding,float default_scale_when_already_legible,float & scale,IntPoint & scroll)695 void WebViewImpl::ComputeScaleAndScrollForBlockRect(
696 const gfx::Point& hit_point_in_root_frame,
697 const WebRect& block_rect_in_root_frame,
698 float padding,
699 float default_scale_when_already_legible,
700 float& scale,
701 IntPoint& scroll) {
702 scale = PageScaleFactor();
703 scroll = IntPoint();
704
705 WebRect rect = block_rect_in_root_frame;
706
707 if (!rect.IsEmpty()) {
708 float default_margin = doubleTapZoomContentDefaultMargin;
709 float minimum_margin = doubleTapZoomContentMinimumMargin;
710 // We want the margins to have the same physical size, which means we
711 // need to express them in post-scale size. To do that we'd need to know
712 // the scale we're scaling to, but that depends on the margins. Instead
713 // we express them as a fraction of the target rectangle: this will be
714 // correct if we end up fully zooming to it, and won't matter if we
715 // don't.
716 rect = WidenRectWithinPageBounds(
717 rect, static_cast<int>(default_margin * rect.width / size_.width()),
718 static_cast<int>(minimum_margin * rect.width / size_.width()));
719 // Fit block to screen, respecting limits.
720 scale = static_cast<float>(size_.width()) / rect.width;
721 scale = std::min(scale, MaximumLegiblePageScale());
722 if (PageScaleFactor() < default_scale_when_already_legible)
723 scale = std::max(scale, default_scale_when_already_legible);
724 scale = ClampPageScaleFactorToLimits(scale);
725 }
726
727 // FIXME: If this is being called for auto zoom during find in page,
728 // then if the user manually zooms in it'd be nice to preserve the
729 // relative increase in zoom they caused (if they zoom out then it's ok
730 // to zoom them back in again). This isn't compatible with our current
731 // double-tap zoom strategy (fitting the containing block to the screen)
732 // though.
733
734 float screen_width = size_.width() / scale;
735 float screen_height = size_.height() / scale;
736
737 // Scroll to vertically align the block.
738 if (rect.height < screen_height) {
739 // Vertically center short blocks.
740 rect.y -= 0.5 * (screen_height - rect.height);
741 } else {
742 // Ensure position we're zooming to (+ padding) isn't off the bottom of
743 // the screen.
744 rect.y = std::max<float>(
745 rect.y, hit_point_in_root_frame.y() + padding - screen_height);
746 } // Otherwise top align the block.
747
748 // Do the same thing for horizontal alignment.
749 if (rect.width < screen_width) {
750 rect.x -= 0.5 * (screen_width - rect.width);
751 } else {
752 rect.x = std::max<float>(
753 rect.x, hit_point_in_root_frame.x() + padding - screen_width);
754 }
755 scroll.SetX(rect.x);
756 scroll.SetY(rect.y);
757
758 scale = ClampPageScaleFactorToLimits(scale);
759 scroll = MainFrameImpl()->GetFrameView()->RootFrameToDocument(scroll);
760 scroll =
761 GetPage()->GetVisualViewport().ClampDocumentOffsetAtScale(scroll, scale);
762 }
763
FindCursorDefiningAncestor(Node * node,LocalFrame * frame)764 static Node* FindCursorDefiningAncestor(Node* node, LocalFrame* frame) {
765 // Go up the tree to find the node that defines a mouse cursor style
766 while (node) {
767 if (node->GetLayoutObject()) {
768 ECursor cursor = node->GetLayoutObject()->Style()->Cursor();
769 if (cursor != ECursor::kAuto ||
770 frame->GetEventHandler().UseHandCursor(node, node->IsLink()))
771 break;
772 }
773 node = LayoutTreeBuilderTraversal::Parent(*node);
774 }
775
776 return node;
777 }
778
ShowsHandCursor(Node * node,LocalFrame * frame)779 static bool ShowsHandCursor(Node* node, LocalFrame* frame) {
780 if (!node || !node->GetLayoutObject())
781 return false;
782
783 ECursor cursor = node->GetLayoutObject()->Style()->Cursor();
784 return cursor == ECursor::kPointer ||
785 (cursor == ECursor::kAuto &&
786 frame->GetEventHandler().UseHandCursor(node, node->IsLink()));
787 }
788
789 // This is for tap (link) highlight and is tested in
790 // link_highlight_impl_test.cc.
BestTapNode(const GestureEventWithHitTestResults & targeted_tap_event)791 Node* WebViewImpl::BestTapNode(
792 const GestureEventWithHitTestResults& targeted_tap_event) {
793 TRACE_EVENT0("input", "WebViewImpl::bestTapNode");
794
795 Page* page = page_.Get();
796 if (!page || !page->MainFrame())
797 return nullptr;
798
799 Node* best_touch_node = targeted_tap_event.GetHitTestResult().InnerNode();
800 if (!best_touch_node)
801 return nullptr;
802
803 // We might hit something like an image map that has no layoutObject on it
804 // Walk up the tree until we have a node with an attached layoutObject
805 while (!best_touch_node->GetLayoutObject()) {
806 best_touch_node = LayoutTreeBuilderTraversal::Parent(*best_touch_node);
807 if (!best_touch_node)
808 return nullptr;
809 }
810
811 // Editable nodes should not be highlighted (e.g., <input>)
812 if (HasEditableStyle(*best_touch_node))
813 return nullptr;
814
815 Node* cursor_defining_ancestor = FindCursorDefiningAncestor(
816 best_touch_node, page->DeprecatedLocalMainFrame());
817 // We show a highlight on tap only when the current node shows a hand cursor
818 if (!cursor_defining_ancestor ||
819 !ShowsHandCursor(cursor_defining_ancestor,
820 page->DeprecatedLocalMainFrame())) {
821 return nullptr;
822 }
823
824 // We should pick the largest enclosing node with hand cursor set. We do this
825 // by first jumping up to cursorDefiningAncestor (which is already known to
826 // have hand cursor set). Then we locate the next cursor-defining ancestor up
827 // in the the tree and repeat the jumps as long as the node has hand cursor
828 // set.
829 do {
830 best_touch_node = cursor_defining_ancestor;
831 cursor_defining_ancestor = FindCursorDefiningAncestor(
832 LayoutTreeBuilderTraversal::Parent(*best_touch_node),
833 page->DeprecatedLocalMainFrame());
834 } while (cursor_defining_ancestor &&
835 ShowsHandCursor(cursor_defining_ancestor,
836 page->DeprecatedLocalMainFrame()));
837
838 // This happens in cases like:
839 // <div style="display: contents; cursor: pointer">Text</div>.
840 // The text node inherits cursor: pointer and the div doesn't have a
841 // LayoutObject, so |best_touch_node| is the text node here. We should not
842 // return the text node because it can't have touch actions.
843 if (best_touch_node->IsTextNode())
844 return nullptr;
845
846 return best_touch_node;
847 }
848
EnableTapHighlightAtPoint(const GestureEventWithHitTestResults & targeted_tap_event)849 void WebViewImpl::EnableTapHighlightAtPoint(
850 const GestureEventWithHitTestResults& targeted_tap_event) {
851 Node* touch_node = BestTapNode(targeted_tap_event);
852 GetPage()->GetLinkHighlight().SetTapHighlight(touch_node);
853 UpdateLifecycle(WebLifecycleUpdate::kAll,
854 DocumentUpdateReason::kTapHighlight);
855 }
856
AnimateDoubleTapZoom(const gfx::Point & point_in_root_frame,const WebRect & rect_to_zoom)857 void WebViewImpl::AnimateDoubleTapZoom(const gfx::Point& point_in_root_frame,
858 const WebRect& rect_to_zoom) {
859 DCHECK(MainFrameImpl());
860
861 float scale;
862 IntPoint scroll;
863
864 ComputeScaleAndScrollForBlockRect(
865 point_in_root_frame, rect_to_zoom, touchPointPadding,
866 MinimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio, scale,
867 scroll);
868
869 bool still_at_previous_double_tap_scale =
870 (PageScaleFactor() == double_tap_zoom_page_scale_factor_ &&
871 double_tap_zoom_page_scale_factor_ != MinimumPageScaleFactor()) ||
872 double_tap_zoom_pending_;
873
874 bool scale_unchanged = fabs(PageScaleFactor() - scale) < minScaleDifference;
875 bool should_zoom_out = rect_to_zoom.IsEmpty() || scale_unchanged ||
876 still_at_previous_double_tap_scale;
877
878 bool is_animating;
879
880 if (should_zoom_out) {
881 scale = MinimumPageScaleFactor();
882 IntPoint target_position =
883 MainFrameImpl()->GetFrameView()->RootFrameToDocument(
884 IntPoint(point_in_root_frame.x(), point_in_root_frame.y()));
885 is_animating = StartPageScaleAnimation(target_position, true, scale,
886 kDoubleTapZoomAnimationDuration);
887 } else {
888 is_animating = StartPageScaleAnimation(scroll, false, scale,
889 kDoubleTapZoomAnimationDuration);
890 }
891
892 // TODO(dglazkov): The only reason why we're using isAnimating and not just
893 // checking for layer_tree_view_->HasPendingPageScaleAnimation() is because of
894 // fake page scale animation plumbing for testing, which doesn't actually
895 // initiate a page scale animation.
896 if (is_animating) {
897 double_tap_zoom_page_scale_factor_ = scale;
898 double_tap_zoom_pending_ = true;
899 }
900 }
901
ZoomToFindInPageRect(const WebRect & rect_in_root_frame)902 void WebViewImpl::ZoomToFindInPageRect(const WebRect& rect_in_root_frame) {
903 DCHECK(MainFrameImpl());
904
905 WebRect block_bounds = MainFrameImpl()->FrameWidgetImpl()->ComputeBlockBound(
906 gfx::Point(rect_in_root_frame.x + rect_in_root_frame.width / 2,
907 rect_in_root_frame.y + rect_in_root_frame.height / 2),
908 true);
909
910 if (block_bounds.IsEmpty()) {
911 // Keep current scale (no need to scroll as x,y will normally already
912 // be visible). FIXME: Revisit this if it isn't always true.
913 return;
914 }
915
916 float scale;
917 IntPoint scroll;
918
919 ComputeScaleAndScrollForBlockRect(
920 gfx::Point(rect_in_root_frame.x, rect_in_root_frame.y), block_bounds,
921 nonUserInitiatedPointPadding, MinimumPageScaleFactor(), scale, scroll);
922
923 StartPageScaleAnimation(scroll, false, scale, kFindInPageAnimationDuration);
924 }
925
926 #if !defined(OS_MAC)
927 // Mac has no way to open a context menu based on a keyboard event.
SendContextMenuEvent()928 WebInputEventResult WebViewImpl::SendContextMenuEvent() {
929 // The contextMenuController() holds onto the last context menu that was
930 // popped up on the page until a new one is created. We need to clear
931 // this menu before propagating the event through the DOM so that we can
932 // detect if we create a new menu for this event, since we won't create
933 // a new menu if the DOM swallows the event and the defaultEventHandler does
934 // not run.
935 GetPage()->GetContextMenuController().ClearContextMenu();
936
937 {
938 ContextMenuAllowedScope scope;
939 Frame* focused_frame = GetPage()->GetFocusController().FocusedOrMainFrame();
940 auto* focused_local_frame = DynamicTo<LocalFrame>(focused_frame);
941 if (!focused_local_frame)
942 return WebInputEventResult::kNotHandled;
943 // Firefox reveal focus based on "keydown" event but not "contextmenu"
944 // event, we match FF.
945 if (Element* focused_element =
946 focused_local_frame->GetDocument()->FocusedElement())
947 focused_element->scrollIntoViewIfNeeded();
948 return focused_local_frame->GetEventHandler().ShowNonLocatedContextMenu(
949 nullptr, kMenuSourceKeyboard);
950 }
951 }
952 #else
SendContextMenuEvent()953 WebInputEventResult WebViewImpl::SendContextMenuEvent() {
954 return WebInputEventResult::kNotHandled;
955 }
956 #endif
957
OpenPagePopup(PagePopupClient * client)958 WebPagePopupImpl* WebViewImpl::OpenPagePopup(PagePopupClient* client) {
959 DCHECK(client);
960
961 // This guarantees there is never more than 1 PagePopup active at a time.
962 CancelPagePopup();
963 DCHECK(!page_popup_);
964
965 WebLocalFrameImpl* frame = WebLocalFrameImpl::FromFrame(
966 client->OwnerElement().GetDocument().GetFrame()->LocalFrameRoot());
967 WebPagePopup* popup_widget = web_view_client_->CreatePopup(frame);
968 // CreatePopup returns nullptr if this renderer process is about to die.
969 if (!popup_widget)
970 return nullptr;
971 page_popup_ = To<WebPagePopupImpl>(popup_widget);
972 page_popup_->Initialize(this, client);
973 EnablePopupMouseWheelEventListener(frame);
974 return page_popup_.get();
975 }
976
CancelPagePopup()977 void WebViewImpl::CancelPagePopup() {
978 if (page_popup_)
979 page_popup_->Cancel();
980 }
981
ClosePagePopup(PagePopup * popup)982 void WebViewImpl::ClosePagePopup(PagePopup* popup) {
983 DCHECK(popup);
984 auto* popup_impl = To<WebPagePopupImpl>(popup);
985 DCHECK_EQ(page_popup_.get(), popup_impl);
986 if (page_popup_.get() != popup_impl)
987 return;
988 page_popup_->ClosePopup();
989 }
990
CleanupPagePopup()991 void WebViewImpl::CleanupPagePopup() {
992 page_popup_ = nullptr;
993 DisablePopupMouseWheelEventListener();
994 }
995
UpdatePagePopup()996 void WebViewImpl::UpdatePagePopup() {
997 if (page_popup_)
998 page_popup_->Update();
999 }
1000
EnablePopupMouseWheelEventListener(WebLocalFrameImpl * local_root)1001 void WebViewImpl::EnablePopupMouseWheelEventListener(
1002 WebLocalFrameImpl* local_root) {
1003 DCHECK(!popup_mouse_wheel_event_listener_);
1004 Document* document = local_root->GetDocument();
1005 DCHECK(document);
1006 // We register an empty event listener, EmptyEventListener, so that mouse
1007 // wheel events get sent to the WebView.
1008 popup_mouse_wheel_event_listener_ =
1009 MakeGarbageCollected<EmptyEventListener>();
1010 document->addEventListener(event_type_names::kMousewheel,
1011 popup_mouse_wheel_event_listener_, false);
1012 local_root_with_empty_mouse_wheel_listener_ = local_root;
1013 }
1014
DisablePopupMouseWheelEventListener()1015 void WebViewImpl::DisablePopupMouseWheelEventListener() {
1016 // TODO(kenrb): Concerns the same as in enablePopupMouseWheelEventListener.
1017 // See https://crbug.com/566130
1018 DCHECK(popup_mouse_wheel_event_listener_);
1019 Document* document =
1020 local_root_with_empty_mouse_wheel_listener_->GetDocument();
1021 DCHECK(document);
1022 // Document may have already removed the event listener, for instance, due
1023 // to a navigation, but remove it anyway.
1024 document->removeEventListener(event_type_names::kMousewheel,
1025 popup_mouse_wheel_event_listener_.Release(),
1026 false);
1027 local_root_with_empty_mouse_wheel_listener_ = nullptr;
1028 }
1029
PagePopupWindow() const1030 LocalDOMWindow* WebViewImpl::PagePopupWindow() const {
1031 return page_popup_ ? page_popup_->Window() : nullptr;
1032 }
1033
FocusedCoreFrame() const1034 Frame* WebViewImpl::FocusedCoreFrame() const {
1035 Page* page = page_.Get();
1036 return page ? page->GetFocusController().FocusedOrMainFrame() : nullptr;
1037 }
1038
1039 // WebWidget ------------------------------------------------------------------
1040
Close()1041 void WebViewImpl::Close() {
1042 // Closership is a single relationship, so only 1 call to Close() should
1043 // occur.
1044 CHECK(page_);
1045 DCHECK(AllInstances().Contains(this));
1046 AllInstances().erase(this);
1047
1048 // Invalidate any weak ptrs as we are starting to shutdown.
1049 weak_ptr_factory_.InvalidateWeakPtrs();
1050
1051 // Initiate shutdown for the entire frameset. This will cause a lot of
1052 // notifications to be sent. This will detach all frames in this WebView's
1053 // frame tree.
1054 page_->WillBeDestroyed();
1055 page_.Clear();
1056
1057 // Reset the delegate to prevent notifications being sent as we're being
1058 // deleted.
1059 web_view_client_ = nullptr;
1060
1061 Release(); // Balances a reference acquired in WebView::Create
1062 }
1063
Size()1064 gfx::Size WebViewImpl::Size() {
1065 return size_;
1066 }
1067
ResizeVisualViewport(const gfx::Size & new_size)1068 void WebViewImpl::ResizeVisualViewport(const gfx::Size& new_size) {
1069 GetPage()->GetVisualViewport().SetSize(WebSize(new_size));
1070 GetPage()->GetVisualViewport().ClampToBoundaries();
1071 }
1072
UpdateICBAndResizeViewport(const IntSize & visible_viewport_size)1073 void WebViewImpl::UpdateICBAndResizeViewport(
1074 const IntSize& visible_viewport_size) {
1075 // We'll keep the initial containing block size from changing when the top
1076 // controls hide so that the ICB will always be the same size as the
1077 // viewport with the browser controls shown.
1078 IntSize icb_size = IntSize(size_);
1079 if (GetBrowserControls().PermittedState() ==
1080 cc::BrowserControlsState::kBoth &&
1081 !GetBrowserControls().ShrinkViewport()) {
1082 icb_size.Expand(0, -(GetBrowserControls().TotalHeight() -
1083 GetBrowserControls().TotalMinHeight()));
1084 }
1085
1086 GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(icb_size);
1087
1088 UpdatePageDefinedViewportConstraints(MainFrameImpl()
1089 ->GetFrame()
1090 ->GetDocument()
1091 ->GetViewportData()
1092 .GetViewportDescription());
1093 UpdateMainFrameLayoutSize();
1094
1095 GetPage()->GetVisualViewport().SetSize(visible_viewport_size);
1096
1097 if (MainFrameImpl()->GetFrameView()) {
1098 MainFrameImpl()->GetFrameView()->SetInitialViewportSize(icb_size);
1099 if (!MainFrameImpl()->GetFrameView()->NeedsLayout())
1100 resize_viewport_anchor_->ResizeFrameView(MainFrameSize());
1101 }
1102
1103 // The boundaries are not properly established until after the frame view is
1104 // also resized, as demonstrated by
1105 // VisualViewportTest.TestBrowserControlsAdjustmentAndResize.
1106 GetPage()->GetVisualViewport().ClampToBoundaries();
1107 }
1108
UpdateBrowserControlsConstraint(cc::BrowserControlsState constraint)1109 void WebViewImpl::UpdateBrowserControlsConstraint(
1110 cc::BrowserControlsState constraint) {
1111 cc::BrowserControlsState old_permitted_state =
1112 GetBrowserControls().PermittedState();
1113
1114 GetBrowserControls().UpdateConstraintsAndState(
1115 constraint, cc::BrowserControlsState::kBoth);
1116
1117 // If the controls are going from a locked hidden to unlocked state, or vice
1118 // versa, the ICB size needs to change but we can't rely on getting a
1119 // WebViewImpl::resize since the top controls shown state may not have
1120 // changed.
1121 if ((old_permitted_state == cc::BrowserControlsState::kHidden &&
1122 constraint == cc::BrowserControlsState::kBoth) ||
1123 (old_permitted_state == cc::BrowserControlsState::kBoth &&
1124 constraint == cc::BrowserControlsState::kHidden)) {
1125 UpdateICBAndResizeViewport(GetPage()->GetVisualViewport().Size());
1126 }
1127 }
1128
DidUpdateBrowserControls()1129 void WebViewImpl::DidUpdateBrowserControls() {
1130 // BrowserControls are a feature whereby the browser can introduce an
1131 // interactable element [e.g. search box] that grows/shrinks in height as the
1132 // user scrolls the web contents.
1133 //
1134 // This method is called by the BrowserControls class to let the compositor
1135 // know that the browser controls have been updated. This is only relevant if
1136 // the main frame is local because BrowserControls only affects the main
1137 // frame's viewport, and are only affected by main frame scrolling.
1138 //
1139 // The relevant state is stored on the BrowserControls object even if the main
1140 // frame is remote. If the main frame becomes local, the state will be
1141 // restored by the first commit, since the state is checked in every call to
1142 // ApplyScrollAndScale().
1143 WebLocalFrameImpl* main_frame = MainFrameImpl();
1144 if (!main_frame)
1145 return;
1146
1147 WebFrameWidgetBase* widget = main_frame->LocalRootFrameWidget();
1148 widget->SetBrowserControlsShownRatio(GetBrowserControls().TopShownRatio(),
1149 GetBrowserControls().BottomShownRatio());
1150 widget->SetBrowserControlsParams(GetBrowserControls().Params());
1151
1152 VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
1153
1154 {
1155 // This object will save the current visual viewport offset w.r.t. the
1156 // document and restore it when the object goes out of scope. It's
1157 // needed since the browser controls adjustment will change the maximum
1158 // scroll offset and we may need to reposition them to keep the user's
1159 // apparent position unchanged.
1160 ResizeViewportAnchor::ResizeScope resize_scope(*resize_viewport_anchor_);
1161
1162 visual_viewport.SetBrowserControlsAdjustment(
1163 GetBrowserControls().UnreportedSizeAdjustment());
1164 }
1165 }
1166
GetBrowserControls()1167 BrowserControls& WebViewImpl::GetBrowserControls() {
1168 return GetPage()->GetBrowserControls();
1169 }
1170
ResizeViewWhileAnchored(cc::BrowserControlsParams params,const IntSize & visible_viewport_size)1171 void WebViewImpl::ResizeViewWhileAnchored(
1172 cc::BrowserControlsParams params,
1173 const IntSize& visible_viewport_size) {
1174 DCHECK(MainFrameImpl());
1175
1176 GetBrowserControls().SetParams(params);
1177
1178 {
1179 // Avoids unnecessary invalidations while various bits of state in
1180 // TextAutosizer are updated.
1181 TextAutosizer::DeferUpdatePageInfo defer_update_page_info(GetPage());
1182 LocalFrameView* frame_view = MainFrameImpl()->GetFrameView();
1183 IntSize old_size = frame_view->Size();
1184 UpdateICBAndResizeViewport(visible_viewport_size);
1185 IntSize new_size = frame_view->Size();
1186 frame_view->MarkViewportConstrainedObjectsForLayout(
1187 old_size.Width() != new_size.Width(),
1188 old_size.Height() != new_size.Height());
1189 }
1190
1191 fullscreen_controller_->UpdateSize();
1192
1193 // Update lifecycle phases immediately to recalculate the minimum scale limit
1194 // for rotation anchoring, and to make sure that no lifecycle states are
1195 // stale if this WebView is embedded in another one.
1196 UpdateLifecycle(WebLifecycleUpdate::kAll, DocumentUpdateReason::kSizeChange);
1197 }
1198
ResizeWithBrowserControls(const gfx::Size & new_size,float top_controls_height,float bottom_controls_height,bool browser_controls_shrink_layout)1199 void WebViewImpl::ResizeWithBrowserControls(
1200 const gfx::Size& new_size,
1201 float top_controls_height,
1202 float bottom_controls_height,
1203 bool browser_controls_shrink_layout) {
1204 ResizeWithBrowserControls(
1205 new_size, new_size,
1206 {top_controls_height, GetBrowserControls().TopMinHeight(),
1207 bottom_controls_height, GetBrowserControls().BottomMinHeight(),
1208 GetBrowserControls().AnimateHeightChanges(),
1209 browser_controls_shrink_layout});
1210 }
1211
ResizeWithBrowserControls(const gfx::Size & main_frame_widget_size,const gfx::Size & visible_viewport_size,cc::BrowserControlsParams browser_controls_params)1212 void WebViewImpl::ResizeWithBrowserControls(
1213 const gfx::Size& main_frame_widget_size,
1214 const gfx::Size& visible_viewport_size,
1215 cc::BrowserControlsParams browser_controls_params) {
1216 if (should_auto_resize_) {
1217 // When auto-resizing only the viewport size comes from the browser, while
1218 // the widget size is determined in the renderer.
1219 ResizeVisualViewport(visible_viewport_size);
1220 return;
1221 }
1222
1223 if (size_ == main_frame_widget_size &&
1224 GetPage()->GetVisualViewport().Size() == IntSize(visible_viewport_size) &&
1225 GetBrowserControls().Params() == browser_controls_params)
1226 return;
1227
1228 if (GetPage()->MainFrame() && !GetPage()->MainFrame()->IsLocalFrame()) {
1229 // Viewport resize for a remote main frame does not require any
1230 // particular action, but the state needs to reflect the correct size
1231 // so that it can be used for initialization if the main frame gets
1232 // swapped to a LocalFrame at a later time.
1233 size_ = main_frame_widget_size;
1234 GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(
1235 IntSize(size_));
1236 GetPage()->GetVisualViewport().SetSize(IntSize(size_));
1237 GetPage()->GetBrowserControls().SetParams(browser_controls_params);
1238 return;
1239 }
1240
1241 WebLocalFrameImpl* main_frame = MainFrameImpl();
1242 if (!main_frame)
1243 return;
1244
1245 LocalFrameView* view = main_frame->GetFrameView();
1246 if (!view)
1247 return;
1248
1249 VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
1250
1251 bool is_rotation =
1252 GetPage()->GetSettings().GetMainFrameResizesAreOrientationChanges() &&
1253 size_.width() && ContentsSize().Width() &&
1254 main_frame_widget_size.width() != size_.width() &&
1255 !fullscreen_controller_->IsFullscreenOrTransitioning();
1256 size_ = main_frame_widget_size;
1257
1258 FloatSize viewport_anchor_coords(viewportAnchorCoordX, viewportAnchorCoordY);
1259 if (is_rotation) {
1260 RotationViewportAnchor anchor(*view, visual_viewport,
1261 viewport_anchor_coords,
1262 GetPageScaleConstraintsSet());
1263 ResizeViewWhileAnchored(browser_controls_params,
1264 IntSize(visible_viewport_size));
1265 } else {
1266 ResizeViewportAnchor::ResizeScope resize_scope(*resize_viewport_anchor_);
1267 ResizeViewWhileAnchored(browser_controls_params,
1268 IntSize(visible_viewport_size));
1269 }
1270 SendResizeEventForMainFrame();
1271 }
1272
Resize(const gfx::Size & new_size)1273 void WebViewImpl::Resize(const gfx::Size& new_size) {
1274 if (should_auto_resize_ || size_ == new_size)
1275 return;
1276
1277 ResizeWithBrowserControls(new_size, GetBrowserControls().TopHeight(),
1278 GetBrowserControls().BottomHeight(),
1279 GetBrowserControls().ShrinkViewport());
1280 }
1281
SetScreenOrientationOverrideForTesting(base::Optional<blink::mojom::ScreenOrientation> orientation)1282 void WebViewImpl::SetScreenOrientationOverrideForTesting(
1283 base::Optional<blink::mojom::ScreenOrientation> orientation) {
1284 screen_orientation_override_ = orientation;
1285
1286 // Since we updated the override value, notify all widgets.
1287 for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) {
1288 if (frame->IsWebLocalFrame()) {
1289 if (WebFrameWidgetBase* widget = static_cast<WebFrameWidgetBase*>(
1290 frame->ToWebLocalFrame()->FrameWidget()))
1291 widget->UpdateScreenInfo(widget->GetScreenInfo());
1292 }
1293 }
1294 }
1295
UseSynchronousResizeModeForTesting(bool enable)1296 void WebViewImpl::UseSynchronousResizeModeForTesting(bool enable) {
1297 web_widget_->UseSynchronousResizeModeForTesting(enable);
1298 }
1299
SetWindowRectSynchronouslyForTesting(const gfx::Rect & new_window_rect)1300 void WebViewImpl::SetWindowRectSynchronouslyForTesting(
1301 const gfx::Rect& new_window_rect) {
1302 web_widget_->SetWindowRectSynchronouslyForTesting(new_window_rect);
1303 }
1304
1305 base::Optional<mojom::blink::ScreenOrientation>
ScreenOrientationOverride()1306 WebViewImpl::ScreenOrientationOverride() {
1307 return screen_orientation_override_;
1308 }
1309
DidEnterFullscreen()1310 void WebViewImpl::DidEnterFullscreen() {
1311 fullscreen_controller_->DidEnterFullscreen();
1312 }
1313
DidExitFullscreen()1314 void WebViewImpl::DidExitFullscreen() {
1315 fullscreen_controller_->DidExitFullscreen();
1316 }
1317
SetMainFrameViewWidget(WebViewFrameWidget * widget)1318 void WebViewImpl::SetMainFrameViewWidget(WebViewFrameWidget* widget) {
1319 web_widget_ = widget;
1320 }
1321
SetMouseOverURL(const KURL & url)1322 void WebViewImpl::SetMouseOverURL(const KURL& url) {
1323 mouse_over_url_ = url;
1324 UpdateTargetURL(mouse_over_url_, focus_url_);
1325 }
1326
SetKeyboardFocusURL(const KURL & url)1327 void WebViewImpl::SetKeyboardFocusURL(const KURL& url) {
1328 focus_url_ = url;
1329 UpdateTargetURL(focus_url_, mouse_over_url_);
1330 }
1331
MainFrameViewWidget()1332 WebViewFrameWidget* WebViewImpl::MainFrameViewWidget() {
1333 return web_widget_;
1334 }
1335
UpdateLifecycle(WebLifecycleUpdate requested_update,DocumentUpdateReason reason)1336 void WebViewImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
1337 DocumentUpdateReason reason) {
1338 TRACE_EVENT0("blink", "WebViewImpl::updateAllLifecyclePhases");
1339 if (!MainFrameImpl())
1340 return;
1341
1342 PageWidgetDelegate::UpdateLifecycle(*page_, *MainFrameImpl()->GetFrame(),
1343 requested_update, reason);
1344 if (requested_update != WebLifecycleUpdate::kAll)
1345 return;
1346
1347 UpdatePagePopup();
1348
1349 // There is no background color for non-composited WebViews (eg printing).
1350 if (does_composite_) {
1351 SkColor background_color = BackgroundColor();
1352 MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(background_color);
1353 if (background_color != last_background_color_) {
1354 last_background_color_ = background_color;
1355 if (Page* page = page_.Get()) {
1356 if (auto* main_local_frame = DynamicTo<LocalFrame>(page->MainFrame())) {
1357 main_local_frame->DidChangeBackgroundColor(background_color,
1358 false /* color_adjust */);
1359 }
1360 }
1361 }
1362 }
1363
1364 if (LocalFrameView* view = MainFrameImpl()->GetFrameView()) {
1365 LocalFrame* frame = MainFrameImpl()->GetFrame();
1366 WebFrameWidgetBase* frame_widget =
1367 WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
1368
1369 if (should_dispatch_first_visually_non_empty_layout_ &&
1370 view->IsVisuallyNonEmpty()) {
1371 should_dispatch_first_visually_non_empty_layout_ = false;
1372 // TODO(esprehn): Move users of this callback to something
1373 // better, the heuristic for "visually non-empty" is bad.
1374 frame_widget->DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
1375 }
1376
1377 if (should_dispatch_first_layout_after_finished_parsing_ &&
1378 frame->GetDocument()->HasFinishedParsing()) {
1379 should_dispatch_first_layout_after_finished_parsing_ = false;
1380 frame_widget->DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
1381 }
1382
1383 if (should_dispatch_first_layout_after_finished_loading_ &&
1384 frame->GetDocument()->IsLoadCompleted()) {
1385 should_dispatch_first_layout_after_finished_loading_ = false;
1386 frame_widget->DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
1387 }
1388 }
1389 }
1390
PaintContent(cc::PaintCanvas * canvas,const gfx::Rect & rect)1391 void WebViewImpl::PaintContent(cc::PaintCanvas* canvas, const gfx::Rect& rect) {
1392 // This should only be used when compositing is not being used for this
1393 // WebView, and it is painting into the recording of its parent.
1394 DCHECK(!does_composite_);
1395 // Non-composited WebViews always have a local main frame.
1396 DCHECK(MainFrameImpl());
1397
1398 if (rect.IsEmpty())
1399 return;
1400
1401 LocalFrameView& main_view = *MainFrameImpl()->GetFrame()->View();
1402 DCHECK(main_view.GetLayoutView()->GetDocument().Lifecycle().GetState() ==
1403 DocumentLifecycle::kPaintClean);
1404
1405 PaintRecordBuilder builder;
1406 main_view.PaintOutsideOfLifecycle(builder.Context(), kGlobalPaintNormalPhase,
1407 CullRect(IntRect(rect)));
1408 // Don't bother to save/restore here as the caller is expecting the canvas
1409 // to be modified and take care of it.
1410 canvas->clipRect(gfx::RectToSkRect(rect));
1411 builder.EndRecording(*canvas, main_view.GetLayoutView()
1412 ->FirstFragment()
1413 .LocalBorderBoxProperties()
1414 .Unalias());
1415 }
1416
1417 // static
ApplyWebPreferences(const web_pref::WebPreferences & prefs,WebView * web_view)1418 void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
1419 WebView* web_view) {
1420 WebViewImpl* web_view_impl = static_cast<WebViewImpl*>(web_view);
1421 WebSettings* settings = web_view->GetSettings();
1422 ApplyFontsFromMap(prefs.standard_font_family_map,
1423 SetStandardFontFamilyWrapper, settings);
1424 ApplyFontsFromMap(prefs.fixed_font_family_map, SetFixedFontFamilyWrapper,
1425 settings);
1426 ApplyFontsFromMap(prefs.serif_font_family_map, SetSerifFontFamilyWrapper,
1427 settings);
1428 ApplyFontsFromMap(prefs.sans_serif_font_family_map,
1429 SetSansSerifFontFamilyWrapper, settings);
1430 ApplyFontsFromMap(prefs.cursive_font_family_map, SetCursiveFontFamilyWrapper,
1431 settings);
1432 ApplyFontsFromMap(prefs.fantasy_font_family_map, SetFantasyFontFamilyWrapper,
1433 settings);
1434 ApplyFontsFromMap(prefs.pictograph_font_family_map,
1435 SetPictographFontFamilyWrapper, settings);
1436 settings->SetDefaultFontSize(prefs.default_font_size);
1437 settings->SetDefaultFixedFontSize(prefs.default_fixed_font_size);
1438 settings->SetMinimumFontSize(prefs.minimum_font_size);
1439 settings->SetMinimumLogicalFontSize(prefs.minimum_logical_font_size);
1440 settings->SetDefaultTextEncodingName(
1441 WebString::FromASCII(prefs.default_encoding));
1442 settings->SetJavaScriptEnabled(prefs.javascript_enabled);
1443 settings->SetWebSecurityEnabled(prefs.web_security_enabled);
1444 settings->SetLoadsImagesAutomatically(prefs.loads_images_automatically);
1445 settings->SetImagesEnabled(prefs.images_enabled);
1446 settings->SetPluginsEnabled(prefs.plugins_enabled);
1447 settings->SetDOMPasteAllowed(prefs.dom_paste_enabled);
1448 settings->SetTextAreasAreResizable(prefs.text_areas_are_resizable);
1449 settings->SetAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows);
1450 settings->SetDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled);
1451 settings->SetJavaScriptCanAccessClipboard(
1452 prefs.javascript_can_access_clipboard);
1453 RuntimeEnabledFeatures::SetXSLTEnabled(prefs.xslt_enabled);
1454 settings->SetDNSPrefetchingEnabled(prefs.dns_prefetching_enabled);
1455 blink::WebNetworkStateNotifier::SetSaveDataEnabled(prefs.data_saver_enabled);
1456 settings->SetLocalStorageEnabled(prefs.local_storage_enabled);
1457 settings->SetSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled);
1458 settings->SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved(
1459 prefs.target_blank_implies_no_opener_enabled_will_be_removed);
1460 RuntimeEnabledFeatures::SetDatabaseEnabled(prefs.databases_enabled);
1461 settings->SetOfflineWebApplicationCacheEnabled(
1462 prefs.application_cache_enabled);
1463 settings->SetShouldProtectAgainstIpcFlooding(
1464 !prefs.disable_ipc_flooding_protection);
1465 settings->SetHyperlinkAuditingEnabled(prefs.hyperlink_auditing_enabled);
1466 settings->SetCookieEnabled(prefs.cookie_enabled);
1467 settings->SetNavigateOnDragDrop(prefs.navigate_on_drag_drop);
1468 settings->SetThreadedScrollingEnabled(prefs.threaded_scrolling_enabled);
1469
1470 // By default, allow_universal_access_from_file_urls is set to false and thus
1471 // we mitigate attacks from local HTML files by not granting file:// URLs
1472 // universal access. Only test shell will enable this.
1473 settings->SetAllowUniversalAccessFromFileURLs(
1474 prefs.allow_universal_access_from_file_urls);
1475 settings->SetAllowFileAccessFromFileURLs(
1476 prefs.allow_file_access_from_file_urls);
1477
1478 settings->SetWebGL1Enabled(prefs.webgl1_enabled);
1479 settings->SetWebGL2Enabled(prefs.webgl2_enabled);
1480
1481 // Enable WebGL errors to the JS console if requested.
1482 settings->SetWebGLErrorsToConsoleEnabled(
1483 prefs.webgl_errors_to_console_enabled);
1484
1485 settings->SetHideScrollbars(prefs.hide_scrollbars);
1486
1487 // Enable gpu-accelerated 2d canvas if requested on the command line.
1488 RuntimeEnabledFeatures::SetAccelerated2dCanvasEnabled(
1489 prefs.accelerated_2d_canvas_enabled);
1490
1491 // Enable new canvas 2d api features
1492 RuntimeEnabledFeatures::SetNewCanvas2DAPIEnabled(
1493 prefs.new_canvas_2d_api_enabled);
1494
1495 // Disable antialiasing for 2d canvas if requested on the command line.
1496 settings->SetAntialiased2dCanvasEnabled(
1497 !prefs.antialiased_2d_canvas_disabled);
1498
1499 // Disable antialiasing of clips for 2d canvas if requested on the command
1500 // line.
1501 settings->SetAntialiasedClips2dCanvasEnabled(
1502 prefs.antialiased_clips_2d_canvas_enabled);
1503
1504 // Tabs to link is not part of the settings. WebCore calls
1505 // ChromeClient::tabsToLinks which is part of the glue code.
1506 web_view_impl->SetTabsToLinks(prefs.tabs_to_links);
1507
1508 settings->SetAllowRunningOfInsecureContent(
1509 prefs.allow_running_insecure_content);
1510 settings->SetDisableReadingFromCanvas(prefs.disable_reading_from_canvas);
1511 settings->SetStrictMixedContentChecking(prefs.strict_mixed_content_checking);
1512
1513 settings->SetStrictlyBlockBlockableMixedContent(
1514 prefs.strictly_block_blockable_mixed_content);
1515
1516 settings->SetStrictMixedContentCheckingForPlugin(
1517 prefs.block_mixed_plugin_content);
1518
1519 settings->SetStrictPowerfulFeatureRestrictions(
1520 prefs.strict_powerful_feature_restrictions);
1521 settings->SetAllowGeolocationOnInsecureOrigins(
1522 prefs.allow_geolocation_on_insecure_origins);
1523 settings->SetPasswordEchoEnabled(prefs.password_echo_enabled);
1524 settings->SetShouldPrintBackgrounds(prefs.should_print_backgrounds);
1525 settings->SetShouldClearDocumentBackground(
1526 prefs.should_clear_document_background);
1527 settings->SetEnableScrollAnimator(prefs.enable_scroll_animator);
1528 settings->SetPrefersReducedMotion(prefs.prefers_reduced_motion);
1529
1530 RuntimeEnabledFeatures::SetTouchEventFeatureDetectionEnabled(
1531 prefs.touch_event_feature_detection_enabled);
1532 settings->SetMaxTouchPoints(prefs.pointer_events_max_touch_points);
1533 settings->SetAvailablePointerTypes(prefs.available_pointer_types);
1534 settings->SetPrimaryPointerType(prefs.primary_pointer_type);
1535 settings->SetAvailableHoverTypes(prefs.available_hover_types);
1536 settings->SetPrimaryHoverType(prefs.primary_hover_type);
1537 settings->SetBarrelButtonForDragEnabled(prefs.barrel_button_for_drag_enabled);
1538
1539 settings->SetEditingBehavior(prefs.editing_behavior);
1540
1541 settings->SetSupportsMultipleWindows(prefs.supports_multiple_windows);
1542
1543 settings->SetMainFrameClipsContent(!prefs.record_whole_document);
1544
1545 settings->SetSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled);
1546
1547 settings->SetSpatialNavigationEnabled(prefs.spatial_navigation_enabled);
1548 // Spatnav depends on KeyboardFocusableScrollers. The WebUI team has
1549 // disabled KFS because they need more time to update their custom elements,
1550 // crbug.com/907284. Meanwhile, we pre-ship KFS to spatnav users.
1551 if (prefs.spatial_navigation_enabled)
1552 RuntimeEnabledFeatures::SetKeyboardFocusableScrollersEnabled(true);
1553
1554 settings->SetSelectionIncludesAltImageText(true);
1555
1556 settings->SetV8CacheOptions(prefs.v8_cache_options);
1557
1558 settings->SetImageAnimationPolicy(prefs.animation_policy);
1559
1560 settings->SetPresentationRequiresUserGesture(
1561 prefs.user_gesture_required_for_presentation);
1562
1563 if (prefs.text_tracks_enabled) {
1564 settings->SetTextTrackKindUserPreference(
1565 WebSettings::TextTrackKindUserPreference::kCaptions);
1566 } else {
1567 settings->SetTextTrackKindUserPreference(
1568 WebSettings::TextTrackKindUserPreference::kDefault);
1569 }
1570 settings->SetTextTrackBackgroundColor(
1571 WebString::FromASCII(prefs.text_track_background_color));
1572 settings->SetTextTrackTextColor(
1573 WebString::FromASCII(prefs.text_track_text_color));
1574 settings->SetTextTrackTextSize(
1575 WebString::FromASCII(prefs.text_track_text_size));
1576 settings->SetTextTrackTextShadow(
1577 WebString::FromASCII(prefs.text_track_text_shadow));
1578 settings->SetTextTrackFontFamily(
1579 WebString::FromASCII(prefs.text_track_font_family));
1580 settings->SetTextTrackFontStyle(
1581 WebString::FromASCII(prefs.text_track_font_style));
1582 settings->SetTextTrackFontVariant(
1583 WebString::FromASCII(prefs.text_track_font_variant));
1584 settings->SetTextTrackMarginPercentage(prefs.text_track_margin_percentage);
1585 settings->SetTextTrackWindowColor(
1586 WebString::FromASCII(prefs.text_track_window_color));
1587 settings->SetTextTrackWindowPadding(
1588 WebString::FromASCII(prefs.text_track_window_padding));
1589 settings->SetTextTrackWindowRadius(
1590 WebString::FromASCII(prefs.text_track_window_radius));
1591
1592 // Needs to happen before SetDefaultPageScaleLimits below since that'll
1593 // recalculate the final page scale limits and that depends on this setting.
1594 settings->SetShrinksViewportContentToFit(
1595 prefs.shrinks_viewport_contents_to_fit);
1596
1597 // Needs to happen before SetIgnoreViewportTagScaleLimits below.
1598 web_view->SetDefaultPageScaleLimits(prefs.default_minimum_page_scale_factor,
1599 prefs.default_maximum_page_scale_factor);
1600
1601 settings->SetFullscreenSupported(prefs.fullscreen_supported);
1602 settings->SetTextAutosizingEnabled(prefs.text_autosizing_enabled);
1603 settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled);
1604 blink::WebNetworkStateNotifier::SetNetworkQualityWebHoldback(
1605 static_cast<blink::WebEffectiveConnectionType>(
1606 prefs.network_quality_estimator_web_holdback));
1607
1608 settings->SetDontSendKeyEventsToJavascript(
1609 prefs.dont_send_key_events_to_javascript);
1610 settings->SetWebAppScope(WebString::FromASCII(prefs.web_app_scope.spec()));
1611
1612 #if defined(OS_ANDROID)
1613 settings->SetAllowCustomScrollbarInMainFrame(false);
1614 settings->SetAccessibilityFontScaleFactor(prefs.font_scale_factor);
1615 settings->SetDeviceScaleAdjustment(prefs.device_scale_adjustment);
1616 web_view_impl->SetIgnoreViewportTagScaleLimits(prefs.force_enable_zoom);
1617 settings->SetAutoZoomFocusedNodeToLegibleScale(true);
1618 settings->SetDefaultVideoPosterURL(
1619 WebString::FromASCII(prefs.default_video_poster_url.spec()));
1620 settings->SetSupportDeprecatedTargetDensityDPI(
1621 prefs.support_deprecated_target_density_dpi);
1622 settings->SetUseLegacyBackgroundSizeShorthandBehavior(
1623 prefs.use_legacy_background_size_shorthand_behavior);
1624 settings->SetWideViewportQuirkEnabled(prefs.wide_viewport_quirk);
1625 settings->SetUseWideViewport(prefs.use_wide_viewport);
1626 settings->SetForceZeroLayoutHeight(prefs.force_zero_layout_height);
1627 settings->SetViewportMetaMergeContentQuirk(
1628 prefs.viewport_meta_merge_content_quirk);
1629 settings->SetViewportMetaNonUserScalableQuirk(
1630 prefs.viewport_meta_non_user_scalable_quirk);
1631 settings->SetViewportMetaZeroValuesQuirk(
1632 prefs.viewport_meta_zero_values_quirk);
1633 settings->SetClobberUserAgentInitialScaleQuirk(
1634 prefs.clobber_user_agent_initial_scale_quirk);
1635 settings->SetIgnoreMainFrameOverflowHiddenQuirk(
1636 prefs.ignore_main_frame_overflow_hidden_quirk);
1637 settings->SetReportScreenSizeInPhysicalPixelsQuirk(
1638 prefs.report_screen_size_in_physical_pixels_quirk);
1639 settings->SetShouldReuseGlobalForUnownedMainFrame(
1640 prefs.reuse_global_for_unowned_main_frame);
1641 settings->SetPreferHiddenVolumeControls(true);
1642 settings->SetSpellCheckEnabledByDefault(prefs.spellcheck_enabled_by_default);
1643
1644 RuntimeEnabledFeatures::SetVideoFullscreenOrientationLockEnabled(
1645 prefs.video_fullscreen_orientation_lock_enabled);
1646 RuntimeEnabledFeatures::SetVideoRotateToFullscreenEnabled(
1647 prefs.video_rotate_to_fullscreen_enabled);
1648 settings->SetEmbeddedMediaExperienceEnabled(
1649 prefs.embedded_media_experience_enabled);
1650 settings->SetImmersiveModeEnabled(prefs.immersive_mode_enabled);
1651 settings->SetDoNotUpdateSelectionOnMutatingSelectionRange(
1652 prefs.do_not_update_selection_on_mutating_selection_range);
1653 RuntimeEnabledFeatures::SetCSSHexAlphaColorEnabled(
1654 prefs.css_hex_alpha_color_enabled);
1655 RuntimeEnabledFeatures::SetScrollTopLeftInteropEnabled(
1656 prefs.scroll_top_left_interop_enabled);
1657 RuntimeEnabledFeatures::SetSurfaceEmbeddingFeaturesEnabled(
1658 !prefs.disable_features_depending_on_viz);
1659 RuntimeEnabledFeatures::SetAcceleratedSmallCanvasesEnabled(
1660 !prefs.disable_accelerated_small_canvases);
1661 #endif // defined(OS_ANDROID)
1662 settings->SetForceDarkModeEnabled(prefs.force_dark_mode_enabled);
1663
1664 settings->SetAccessibilityAlwaysShowFocus(prefs.always_show_focus);
1665 settings->SetAutoplayPolicy(prefs.autoplay_policy);
1666 settings->SetViewportEnabled(prefs.viewport_enabled);
1667 settings->SetViewportMetaEnabled(prefs.viewport_meta_enabled);
1668 settings->SetViewportStyle(prefs.viewport_style);
1669
1670 settings->SetLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale);
1671 settings->SetMainFrameResizesAreOrientationChanges(
1672 prefs.main_frame_resizes_are_orientation_changes);
1673
1674 settings->SetShowContextMenuOnMouseUp(prefs.context_menu_on_mouse_up);
1675 settings->SetAlwaysShowContextMenuOnTouch(
1676 prefs.always_show_context_menu_on_touch);
1677 settings->SetSmoothScrollForFindEnabled(prefs.smooth_scroll_for_find_enabled);
1678
1679 settings->SetHideDownloadUI(prefs.hide_download_ui);
1680
1681 settings->SetPresentationReceiver(prefs.presentation_receiver);
1682
1683 settings->SetMediaControlsEnabled(prefs.media_controls_enabled);
1684
1685 settings->SetLowPriorityIframesThreshold(
1686 static_cast<blink::WebEffectiveConnectionType>(
1687 prefs.low_priority_iframes_threshold));
1688
1689 settings->SetPictureInPictureEnabled(
1690 prefs.picture_in_picture_enabled &&
1691 GetVideoSurfaceLayerMode() !=
1692 blink::WebMediaPlayer::SurfaceLayerMode::kNever);
1693
1694 settings->SetDataSaverHoldbackWebApi(
1695 prefs.data_saver_holdback_web_api_enabled);
1696
1697 settings->SetLazyLoadEnabled(prefs.lazy_load_enabled);
1698 settings->SetPreferredColorScheme(prefs.preferred_color_scheme);
1699 settings->SetPreferredContrast(prefs.preferred_contrast);
1700
1701 for (const auto& ect_distance_pair :
1702 prefs.lazy_frame_loading_distance_thresholds_px) {
1703 switch (ect_distance_pair.first) {
1704 case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
1705 settings->SetLazyFrameLoadingDistanceThresholdPxUnknown(
1706 ect_distance_pair.second);
1707 continue;
1708 case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE:
1709 settings->SetLazyFrameLoadingDistanceThresholdPxOffline(
1710 ect_distance_pair.second);
1711 continue;
1712 case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
1713 settings->SetLazyFrameLoadingDistanceThresholdPxSlow2G(
1714 ect_distance_pair.second);
1715 continue;
1716 case net::EFFECTIVE_CONNECTION_TYPE_2G:
1717 settings->SetLazyFrameLoadingDistanceThresholdPx2G(
1718 ect_distance_pair.second);
1719 continue;
1720 case net::EFFECTIVE_CONNECTION_TYPE_3G:
1721 settings->SetLazyFrameLoadingDistanceThresholdPx3G(
1722 ect_distance_pair.second);
1723 continue;
1724 case net::EFFECTIVE_CONNECTION_TYPE_4G:
1725 settings->SetLazyFrameLoadingDistanceThresholdPx4G(
1726 ect_distance_pair.second);
1727 continue;
1728 case net::EFFECTIVE_CONNECTION_TYPE_LAST:
1729 continue;
1730 }
1731 NOTREACHED();
1732 }
1733
1734 for (const auto& ect_distance_pair :
1735 prefs.lazy_image_loading_distance_thresholds_px) {
1736 switch (ect_distance_pair.first) {
1737 case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
1738 settings->SetLazyImageLoadingDistanceThresholdPxUnknown(
1739 ect_distance_pair.second);
1740 continue;
1741 case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE:
1742 settings->SetLazyImageLoadingDistanceThresholdPxOffline(
1743 ect_distance_pair.second);
1744 continue;
1745 case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
1746 settings->SetLazyImageLoadingDistanceThresholdPxSlow2G(
1747 ect_distance_pair.second);
1748 continue;
1749 case net::EFFECTIVE_CONNECTION_TYPE_2G:
1750 settings->SetLazyImageLoadingDistanceThresholdPx2G(
1751 ect_distance_pair.second);
1752 continue;
1753 case net::EFFECTIVE_CONNECTION_TYPE_3G:
1754 settings->SetLazyImageLoadingDistanceThresholdPx3G(
1755 ect_distance_pair.second);
1756 continue;
1757 case net::EFFECTIVE_CONNECTION_TYPE_4G:
1758 settings->SetLazyImageLoadingDistanceThresholdPx4G(
1759 ect_distance_pair.second);
1760 continue;
1761 case net::EFFECTIVE_CONNECTION_TYPE_LAST:
1762 continue;
1763 }
1764 NOTREACHED();
1765 }
1766
1767 for (const auto& fully_load_k_pair : prefs.lazy_image_first_k_fully_load) {
1768 switch (fully_load_k_pair.first) {
1769 case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE:
1770 continue;
1771 case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
1772 settings->SetLazyImageFirstKFullyLoadUnknown(fully_load_k_pair.second);
1773 continue;
1774 case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
1775 settings->SetLazyImageFirstKFullyLoadSlow2G(fully_load_k_pair.second);
1776 continue;
1777 case net::EFFECTIVE_CONNECTION_TYPE_2G:
1778 settings->SetLazyImageFirstKFullyLoad2G(fully_load_k_pair.second);
1779 continue;
1780 case net::EFFECTIVE_CONNECTION_TYPE_3G:
1781 settings->SetLazyImageFirstKFullyLoad3G(fully_load_k_pair.second);
1782 continue;
1783 case net::EFFECTIVE_CONNECTION_TYPE_4G:
1784 settings->SetLazyImageFirstKFullyLoad4G(fully_load_k_pair.second);
1785 continue;
1786 case net::EFFECTIVE_CONNECTION_TYPE_LAST:
1787 continue;
1788 }
1789 NOTREACHED();
1790 }
1791
1792 settings->SetTouchDragDropEnabled(prefs.touch_drag_drop_enabled);
1793 settings->SetTouchDragEndContextMenu(prefs.touch_dragend_context_menu);
1794
1795 #if defined(OS_MAC)
1796 web_view_impl->SetMaximumLegibleScale(
1797 prefs.default_maximum_page_scale_factor);
1798 #endif
1799
1800 #if defined(OS_WIN)
1801 RuntimeEnabledFeatures::SetMiddleClickAutoscrollEnabled(true);
1802 #endif
1803
1804 RuntimeEnabledFeatures::SetTranslateServiceEnabled(
1805 prefs.translate_service_available);
1806 }
1807
ThemeChanged()1808 void WebViewImpl::ThemeChanged() {
1809 if (!GetPage())
1810 return;
1811 if (!GetPage()->MainFrame()->IsLocalFrame())
1812 return;
1813 LocalFrameView* view = GetPage()->DeprecatedLocalMainFrame()->View();
1814
1815 WebRect damaged_rect(0, 0, size_.width(), size_.height());
1816 view->InvalidateRect(damaged_rect);
1817 }
1818
EnterFullscreen(LocalFrame & frame,const FullscreenOptions * options,FullscreenRequestType request_type)1819 void WebViewImpl::EnterFullscreen(LocalFrame& frame,
1820 const FullscreenOptions* options,
1821 FullscreenRequestType request_type) {
1822 fullscreen_controller_->EnterFullscreen(frame, options, request_type);
1823 }
1824
ExitFullscreen(LocalFrame & frame)1825 void WebViewImpl::ExitFullscreen(LocalFrame& frame) {
1826 fullscreen_controller_->ExitFullscreen(frame);
1827 }
1828
FullscreenElementChanged(Element * old_element,Element * new_element)1829 void WebViewImpl::FullscreenElementChanged(Element* old_element,
1830 Element* new_element) {
1831 fullscreen_controller_->FullscreenElementChanged(old_element, new_element);
1832 }
1833
HasHorizontalScrollbar()1834 bool WebViewImpl::HasHorizontalScrollbar() {
1835 return MainFrameImpl()
1836 ->GetFrameView()
1837 ->LayoutViewport()
1838 ->HorizontalScrollbar();
1839 }
1840
HasVerticalScrollbar()1841 bool WebViewImpl::HasVerticalScrollbar() {
1842 return MainFrameImpl()->GetFrameView()->LayoutViewport()->VerticalScrollbar();
1843 }
1844
MouseCaptureLost()1845 void WebViewImpl::MouseCaptureLost() {
1846 TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
1847 TRACE_ID_LOCAL(this));
1848 if (page_->DeprecatedLocalMainFrame())
1849 page_->DeprecatedLocalMainFrame()->Client()->SetMouseCapture(false);
1850 }
1851
SetFocus(bool enable)1852 void WebViewImpl::SetFocus(bool enable) {
1853 if (enable)
1854 page_->GetFocusController().SetActive(true);
1855 page_->GetFocusController().SetFocused(enable);
1856 if (enable) {
1857 LocalFrame* focused_frame = page_->GetFocusController().FocusedFrame();
1858 if (focused_frame) {
1859 Element* element = focused_frame->GetDocument()->FocusedElement();
1860 if (element && focused_frame->Selection()
1861 .ComputeVisibleSelectionInDOMTreeDeprecated()
1862 .IsNone()) {
1863 // If the selection was cleared while the WebView was not
1864 // focused, then the focus element shows with a focus ring but
1865 // no caret and does respond to keyboard inputs.
1866 focused_frame->GetDocument()->UpdateStyleAndLayoutTree();
1867 if (element->IsTextControl()) {
1868 element->UpdateFocusAppearance(SelectionBehaviorOnFocus::kRestore);
1869 } else if (HasEditableStyle(*element)) {
1870 // updateFocusAppearance() selects all the text of
1871 // contentseditable DIVs. So we set the selection explicitly
1872 // instead. Note that this has the side effect of moving the
1873 // caret back to the beginning of the text.
1874 Position position(element, 0);
1875 focused_frame->Selection().SetSelectionAndEndTyping(
1876 SelectionInDOMTree::Builder().Collapse(position).Build());
1877 }
1878 }
1879 }
1880 ime_accept_events_ = true;
1881 } else {
1882 CancelPagePopup();
1883
1884 // Clear focus on the currently focused frame if any.
1885 if (!page_)
1886 return;
1887
1888 LocalFrame* frame = DynamicTo<LocalFrame>(page_->MainFrame());
1889 if (!frame)
1890 return;
1891
1892 LocalFrame* focused_frame = FocusedLocalFrameInWidget();
1893 if (focused_frame) {
1894 // Finish an ongoing composition to delete the composition node.
1895 if (focused_frame->GetInputMethodController().HasComposition()) {
1896 // TODO(editing-dev): The use of
1897 // UpdateStyleAndLayout needs to be audited.
1898 // See http://crbug.com/590369 for more details.
1899 focused_frame->GetDocument()->UpdateStyleAndLayout(
1900 DocumentUpdateReason::kFocus);
1901
1902 focused_frame->GetInputMethodController().FinishComposingText(
1903 InputMethodController::kKeepSelection);
1904 }
1905 ime_accept_events_ = false;
1906 }
1907 }
1908 }
1909
1910 // WebView --------------------------------------------------------------------
1911
SettingsImpl()1912 WebSettingsImpl* WebViewImpl::SettingsImpl() {
1913 if (!web_settings_) {
1914 web_settings_ = std::make_unique<WebSettingsImpl>(
1915 &page_->GetSettings(), dev_tools_emulator_.Get());
1916 }
1917 DCHECK(web_settings_);
1918 return web_settings_.get();
1919 }
1920
GetSettings()1921 WebSettings* WebViewImpl::GetSettings() {
1922 return SettingsImpl();
1923 }
1924
PageEncoding() const1925 WebString WebViewImpl::PageEncoding() const {
1926 if (!page_)
1927 return WebString();
1928
1929 auto* main_frame = DynamicTo<LocalFrame>(page_->MainFrame());
1930 if (!main_frame)
1931 return WebString();
1932
1933 // FIXME: Is this check needed?
1934 if (!main_frame->GetDocument()->Loader())
1935 return WebString();
1936
1937 return main_frame->GetDocument()->EncodingName();
1938 }
1939
MainFrame()1940 WebFrame* WebViewImpl::MainFrame() {
1941 Page* page = page_.Get();
1942 return WebFrame::FromFrame(page ? page->MainFrame() : nullptr);
1943 }
1944
MainFrameImpl() const1945 WebLocalFrameImpl* WebViewImpl::MainFrameImpl() const {
1946 Page* page = page_.Get();
1947 if (!page)
1948 return nullptr;
1949 return WebLocalFrameImpl::FromFrame(DynamicTo<LocalFrame>(page->MainFrame()));
1950 }
1951
DidAttachLocalMainFrame()1952 void WebViewImpl::DidAttachLocalMainFrame() {
1953 DCHECK(MainFrameImpl());
1954
1955 LocalFrame* local_frame = MainFrameImpl()->GetFrame();
1956 local_frame->WasAttachedAsLocalMainFrame();
1957
1958 local_frame->GetRemoteNavigationAssociatedInterfaces()->GetInterface(
1959 local_main_frame_host_remote_.BindNewEndpointAndPassReceiver(
1960 GetPage()
1961 ->GetPageScheduler()
1962 ->GetAgentGroupScheduler()
1963 .DefaultTaskRunner()));
1964
1965 if (does_composite_) {
1966 // When attaching a local main frame, set up any state on the compositor.
1967 MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor());
1968 auto& viewport = GetPage()->GetVisualViewport();
1969 MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
1970 viewport.Scale(), viewport.IsPinchGestureActive(),
1971 MinimumPageScaleFactor(), MaximumPageScaleFactor());
1972 // Prevent main frame updates while the main frame is loading until enough
1973 // progress is made and BeginMainFrames are explicitly asked for.
1974 scoped_defer_main_frame_update_ =
1975 MainFrameImpl()->FrameWidgetImpl()->DeferMainFrameUpdate();
1976 }
1977 }
1978
DidAttachRemoteMainFrame()1979 void WebViewImpl::DidAttachRemoteMainFrame() {
1980 DCHECK(!MainFrameImpl());
1981
1982 RemoteFrame* remote_frame = DynamicTo<RemoteFrame>(GetPage()->MainFrame());
1983 remote_frame->WasAttachedAsRemoteMainFrame();
1984
1985 remote_frame->GetRemoteAssociatedInterfaces()->GetInterface(
1986 remote_main_frame_host_remote_.BindNewEndpointAndPassReceiver(
1987 GetPage()
1988 ->GetPageScheduler()
1989 ->GetAgentGroupScheduler()
1990 .DefaultTaskRunner()));
1991 }
1992
DidDetachLocalMainFrame()1993 void WebViewImpl::DidDetachLocalMainFrame() {
1994 // The WebWidgetClient that generated the |scoped_defer_main_frame_update_|
1995 // for a local main frame is going away.
1996 scoped_defer_main_frame_update_ = nullptr;
1997 local_main_frame_host_remote_.reset();
1998 }
1999
DidDetachRemoteMainFrame()2000 void WebViewImpl::DidDetachRemoteMainFrame() {
2001 remote_main_frame_host_remote_.reset();
2002 }
2003
FocusedFrame()2004 WebLocalFrame* WebViewImpl::FocusedFrame() {
2005 Frame* frame = FocusedCoreFrame();
2006 // TODO(yabinh): focusedCoreFrame() should always return a local frame, and
2007 // the following check should be unnecessary.
2008 // See crbug.com/625068
2009 return WebLocalFrameImpl::FromFrame(DynamicTo<LocalFrame>(frame));
2010 }
2011
SetFocusedFrame(WebFrame * frame)2012 void WebViewImpl::SetFocusedFrame(WebFrame* frame) {
2013 if (!frame) {
2014 // Clears the focused frame if any.
2015 Frame* focused_frame = FocusedCoreFrame();
2016 if (auto* focused_local_frame = DynamicTo<LocalFrame>(focused_frame))
2017 focused_local_frame->Selection().SetFrameIsFocused(false);
2018 return;
2019 }
2020 LocalFrame* core_frame = To<WebLocalFrameImpl>(frame)->GetFrame();
2021 core_frame->GetPage()->GetFocusController().SetFocusedFrame(core_frame);
2022 }
2023
2024 // TODO(dglazkov): Remove and replace with Node:hasEditableStyle.
2025 // http://crbug.com/612560
IsElementEditable(const Element * element)2026 static bool IsElementEditable(const Element* element) {
2027 element->GetDocument().UpdateStyleAndLayoutTree();
2028 if (HasEditableStyle(*element))
2029 return true;
2030
2031 if (auto* text_control = ToTextControlOrNull(element)) {
2032 if (!text_control->IsDisabledOrReadOnly())
2033 return true;
2034 }
2035
2036 return EqualIgnoringASCIICase(
2037 element->FastGetAttribute(html_names::kRoleAttr), "textbox");
2038 }
2039
ScrollFocusedEditableElementIntoView()2040 bool WebViewImpl::ScrollFocusedEditableElementIntoView() {
2041 DCHECK(MainFrameImpl());
2042 LocalFrameView* main_frame_view = MainFrameImpl()->GetFrame()->View();
2043 if (!main_frame_view)
2044 return false;
2045
2046 Element* element = FocusedElement();
2047 if (!element || !IsElementEditable(element))
2048 return false;
2049
2050 element->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
2051
2052 LayoutObject* layout_object = element->GetLayoutObject();
2053 if (!layout_object)
2054 return false;
2055
2056 // Since the page has been resized, the layout may have changed. The page
2057 // scale animation started by ZoomAndScrollToFocusedEditableRect will scroll
2058 // only the visual and layout viewports. We'll call ScrollRectToVisible with
2059 // the stop_at_main_frame_layout_viewport param to ensure the element is
2060 // actually visible in the page.
2061 auto params = ScrollAlignment::CreateScrollIntoViewParams(
2062 ScrollAlignment::CenterIfNeeded(), ScrollAlignment::CenterIfNeeded(),
2063 mojom::blink::ScrollType::kProgrammatic, false,
2064 mojom::blink::ScrollBehavior::kInstant);
2065 params->stop_at_main_frame_layout_viewport = true;
2066 layout_object->ScrollRectToVisible(
2067 PhysicalRect(layout_object->AbsoluteBoundingBoxRect()),
2068 std::move(params));
2069
2070 ZoomAndScrollToFocusedEditableElementRect(
2071 main_frame_view->RootFrameToDocument(
2072 element->GetDocument().View()->ConvertToRootFrame(
2073 layout_object->AbsoluteBoundingBoxRect())),
2074 main_frame_view->RootFrameToDocument(
2075 element->GetDocument().View()->ConvertToRootFrame(
2076 element->GetDocument()
2077 .GetFrame()
2078 ->Selection()
2079 .ComputeRectToScroll(kDoNotRevealExtent))),
2080 ShouldZoomToLegibleScale(*element));
2081
2082 return true;
2083 }
2084
ShouldZoomToLegibleScale(const Element & element)2085 bool WebViewImpl::ShouldZoomToLegibleScale(const Element& element) {
2086 bool zoom_into_legible_scale =
2087 web_settings_->AutoZoomFocusedNodeToLegibleScale() &&
2088 !GetPage()->GetVisualViewport().ShouldDisableDesktopWorkarounds();
2089
2090 if (zoom_into_legible_scale) {
2091 // When deciding whether to zoom in on a focused text box, we should
2092 // decide not to zoom in if the user won't be able to zoom out. e.g if the
2093 // textbox is within a touch-action: none container the user can't zoom
2094 // back out.
2095 TouchAction action =
2096 touch_action_util::ComputeEffectiveTouchAction(element);
2097 if (!(static_cast<int>(action) & static_cast<int>(TouchAction::kPinchZoom)))
2098 zoom_into_legible_scale = false;
2099 }
2100
2101 return zoom_into_legible_scale;
2102 }
2103
ZoomAndScrollToFocusedEditableElementRect(const IntRect & element_bounds_in_document,const IntRect & caret_bounds_in_document,bool zoom_into_legible_scale)2104 void WebViewImpl::ZoomAndScrollToFocusedEditableElementRect(
2105 const IntRect& element_bounds_in_document,
2106 const IntRect& caret_bounds_in_document,
2107 bool zoom_into_legible_scale) {
2108 float scale;
2109 IntPoint scroll;
2110 bool need_animation = false;
2111 ComputeScaleAndScrollForEditableElementRects(
2112 element_bounds_in_document, caret_bounds_in_document,
2113 zoom_into_legible_scale, scale, scroll, need_animation);
2114 if (need_animation) {
2115 StartPageScaleAnimation(scroll, false, scale,
2116 kScrollAndScaleAnimationDuration);
2117 }
2118 }
2119
SmoothScroll(int target_x,int target_y,base::TimeDelta duration)2120 void WebViewImpl::SmoothScroll(int target_x,
2121 int target_y,
2122 base::TimeDelta duration) {
2123 IntPoint target_position(target_x, target_y);
2124 StartPageScaleAnimation(target_position, false, PageScaleFactor(), duration);
2125 }
2126
ComputeScaleAndScrollForEditableElementRects(const IntRect & element_bounds_in_document,const IntRect & caret_bounds_in_document,bool zoom_into_legible_scale,float & new_scale,IntPoint & new_scroll,bool & need_animation)2127 void WebViewImpl::ComputeScaleAndScrollForEditableElementRects(
2128 const IntRect& element_bounds_in_document,
2129 const IntRect& caret_bounds_in_document,
2130 bool zoom_into_legible_scale,
2131 float& new_scale,
2132 IntPoint& new_scroll,
2133 bool& need_animation) {
2134 VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
2135
2136 TopDocumentRootScrollerController& controller =
2137 GetPage()->GlobalRootScrollerController();
2138 Node* root_scroller = controller.GlobalRootScroller();
2139
2140 IntRect element_bounds_in_content = element_bounds_in_document;
2141 IntRect caret_bounds_in_content = caret_bounds_in_document;
2142
2143 // If the page has a non-default root scroller then we need to scroll that
2144 // rather than the "real" viewport. However, the given coordinates are in the
2145 // real viewport's document space rather than the root scroller's so we
2146 // perform the conversion here. TODO(bokan): Convert this function to take
2147 // coordinates in absolute/root-frame coordinates to make this more
2148 // consistent. https://crbug.com/931447.
2149 if (root_scroller != MainFrameImpl()->GetFrame()->GetDocument() &&
2150 controller.RootScrollerArea()) {
2151 ScrollOffset offset = controller.RootScrollerArea()->GetScrollOffset();
2152 element_bounds_in_content.Move(FlooredIntSize(offset));
2153 caret_bounds_in_content.Move(FlooredIntSize(offset));
2154 }
2155
2156 if (!zoom_into_legible_scale) {
2157 new_scale = PageScaleFactor();
2158 } else {
2159 // Pick a scale which is reasonably readable. This is the scale at which
2160 // the caret height will become minReadableCaretHeightForNode (adjusted
2161 // for dpi and font scale factor).
2162 const int min_readable_caret_height_for_node =
2163 (element_bounds_in_content.Height() >=
2164 2 * caret_bounds_in_content.Height()
2165 ? minReadableCaretHeightForTextArea
2166 : minReadableCaretHeight) *
2167 MainFrameImpl()->GetFrame()->PageZoomFactor();
2168 new_scale = ClampPageScaleFactorToLimits(
2169 MaximumLegiblePageScale() * min_readable_caret_height_for_node /
2170 caret_bounds_in_content.Height());
2171 new_scale = std::max(new_scale, PageScaleFactor());
2172 }
2173 const float delta_scale = new_scale / PageScaleFactor();
2174
2175 need_animation = false;
2176
2177 // If we are at less than the target zoom level, zoom in.
2178 if (delta_scale > minScaleChangeToTriggerZoom)
2179 need_animation = true;
2180 else
2181 new_scale = PageScaleFactor();
2182
2183 ScrollableArea* root_viewport =
2184 MainFrameImpl()->GetFrame()->View()->GetScrollableArea();
2185
2186 // If the caret is offscreen, then animate.
2187 if (!root_viewport->VisibleContentRect().Contains(caret_bounds_in_content))
2188 need_animation = true;
2189
2190 // If the box is partially offscreen and it's possible to bring it fully
2191 // onscreen, then animate.
2192 if (visual_viewport.VisibleRect().Width() >=
2193 element_bounds_in_content.Width() &&
2194 visual_viewport.VisibleRect().Height() >=
2195 element_bounds_in_content.Height() &&
2196 !root_viewport->VisibleContentRect().Contains(element_bounds_in_content))
2197 need_animation = true;
2198
2199 if (!need_animation)
2200 return;
2201
2202 FloatSize target_viewport_size(visual_viewport.Size());
2203 target_viewport_size.Scale(1 / new_scale);
2204
2205 if (element_bounds_in_content.Width() <= target_viewport_size.Width()) {
2206 // Field is narrower than screen. Try to leave padding on left so field's
2207 // label is visible, but it's more important to ensure entire field is
2208 // onscreen.
2209 int ideal_left_padding = target_viewport_size.Width() * leftBoxRatio;
2210 int max_left_padding_keeping_box_onscreen =
2211 target_viewport_size.Width() - element_bounds_in_content.Width();
2212 new_scroll.SetX(element_bounds_in_content.X() -
2213 std::min<int>(ideal_left_padding,
2214 max_left_padding_keeping_box_onscreen));
2215 } else {
2216 // Field is wider than screen. Try to left-align field, unless caret would
2217 // be offscreen, in which case right-align the caret.
2218 new_scroll.SetX(std::max<int>(
2219 element_bounds_in_content.X(),
2220 caret_bounds_in_content.X() + caret_bounds_in_content.Width() +
2221 caretPadding - target_viewport_size.Width()));
2222 }
2223 if (element_bounds_in_content.Height() <= target_viewport_size.Height()) {
2224 // Field is shorter than screen. Vertically center it.
2225 new_scroll.SetY(
2226 element_bounds_in_content.Y() -
2227 (target_viewport_size.Height() - element_bounds_in_content.Height()) /
2228 2);
2229 } else {
2230 // Field is taller than screen. Try to top align field, unless caret would
2231 // be offscreen, in which case bottom-align the caret.
2232 new_scroll.SetY(std::max<int>(
2233 element_bounds_in_content.Y(),
2234 caret_bounds_in_content.Y() + caret_bounds_in_content.Height() +
2235 caretPadding - target_viewport_size.Height()));
2236 }
2237 }
2238
AdvanceFocus(bool reverse)2239 void WebViewImpl::AdvanceFocus(bool reverse) {
2240 GetPage()->GetFocusController().AdvanceFocus(
2241 reverse ? mojom::blink::FocusType::kBackward
2242 : mojom::blink::FocusType::kForward);
2243 }
2244
ZoomLevel()2245 double WebViewImpl::ZoomLevel() {
2246 return zoom_level_;
2247 }
2248
PropagateZoomFactorToLocalFrameRoots(Frame * frame,float zoom_factor)2249 void WebViewImpl::PropagateZoomFactorToLocalFrameRoots(Frame* frame,
2250 float zoom_factor) {
2251 auto* local_frame = DynamicTo<LocalFrame>(frame);
2252 if (local_frame && local_frame->IsLocalRoot()) {
2253 if (Document* document = local_frame->GetDocument()) {
2254 auto* plugin_document = DynamicTo<PluginDocument>(document);
2255 if (!plugin_document || !plugin_document->GetPluginView()) {
2256 local_frame->SetPageZoomFactor(zoom_factor);
2257 }
2258 }
2259 }
2260
2261 for (Frame* child = frame->Tree().FirstChild(); child;
2262 child = child->Tree().NextSibling())
2263 PropagateZoomFactorToLocalFrameRoots(child, zoom_factor);
2264 }
2265
SetZoomLevel(double zoom_level)2266 double WebViewImpl::SetZoomLevel(double zoom_level) {
2267 double old_zoom_level = zoom_level_;
2268 if (zoom_level < minimum_zoom_level_)
2269 zoom_level_ = minimum_zoom_level_;
2270 else if (zoom_level > maximum_zoom_level_)
2271 zoom_level_ = maximum_zoom_level_;
2272 else
2273 zoom_level_ = zoom_level;
2274
2275 float zoom_factor =
2276 zoom_factor_override_
2277 ? zoom_factor_override_
2278 : static_cast<float>(PageZoomLevelToZoomFactor(zoom_level_));
2279 if (zoom_factor_for_device_scale_factor_) {
2280 if (compositor_device_scale_factor_override_) {
2281 // Adjust the page's DSF so that DevicePixelRatio becomes
2282 // |zoom_factor_for_device_scale_factor_|.
2283 page_->SetDeviceScaleFactorDeprecated(
2284 zoom_factor_for_device_scale_factor_ /
2285 compositor_device_scale_factor_override_);
2286 zoom_factor *= compositor_device_scale_factor_override_;
2287 } else {
2288 page_->SetDeviceScaleFactorDeprecated(1.f);
2289 zoom_factor *= zoom_factor_for_device_scale_factor_;
2290 }
2291 }
2292 PropagateZoomFactorToLocalFrameRoots(page_->MainFrame(), zoom_factor);
2293
2294 if (old_zoom_level != zoom_level_) {
2295 Client()->ZoomLevelChanged();
2296 CancelPagePopup();
2297 }
2298
2299 return zoom_level_;
2300 }
2301
PageScaleFactor() const2302 float WebViewImpl::PageScaleFactor() const {
2303 if (!GetPage())
2304 return 1;
2305
2306 return GetPage()->GetVisualViewport().Scale();
2307 }
2308
ClampPageScaleFactorToLimits(float scale_factor) const2309 float WebViewImpl::ClampPageScaleFactorToLimits(float scale_factor) const {
2310 return GetPageScaleConstraintsSet().FinalConstraints().ClampToConstraints(
2311 scale_factor);
2312 }
2313
SetVisualViewportOffset(const gfx::PointF & offset)2314 void WebViewImpl::SetVisualViewportOffset(const gfx::PointF& offset) {
2315 DCHECK(GetPage());
2316 GetPage()->GetVisualViewport().SetLocation(FloatPoint(offset));
2317 }
2318
VisualViewportOffset() const2319 gfx::PointF WebViewImpl::VisualViewportOffset() const {
2320 DCHECK(GetPage());
2321 return GetPage()->GetVisualViewport().VisibleRect().Location();
2322 }
2323
VisualViewportSize() const2324 gfx::SizeF WebViewImpl::VisualViewportSize() const {
2325 DCHECK(GetPage());
2326 return gfx::SizeF(GetPage()->GetVisualViewport().VisibleRect().Size());
2327 }
2328
SetPageScaleFactorAndLocation(float scale_factor,bool is_pinch_gesture_active,const FloatPoint & location)2329 void WebViewImpl::SetPageScaleFactorAndLocation(float scale_factor,
2330 bool is_pinch_gesture_active,
2331 const FloatPoint& location) {
2332 DCHECK(GetPage());
2333
2334 GetPage()->GetVisualViewport().SetScaleAndLocation(
2335 ClampPageScaleFactorToLimits(scale_factor), is_pinch_gesture_active,
2336 location);
2337 }
2338
SetPageScaleFactor(float scale_factor)2339 void WebViewImpl::SetPageScaleFactor(float scale_factor) {
2340 DCHECK(GetPage());
2341 DCHECK(MainFrameImpl());
2342
2343 MainFrameImpl()->GetFrame()->SetScaleFactor(scale_factor);
2344 }
2345
SetDeviceScaleFactor(float scale_factor)2346 void WebViewImpl::SetDeviceScaleFactor(float scale_factor) {
2347 if (!GetPage())
2348 return;
2349
2350 if (GetPage()->DeviceScaleFactorDeprecated() == scale_factor)
2351 return;
2352
2353 GetPage()->SetDeviceScaleFactorDeprecated(scale_factor);
2354 }
2355
SetZoomFactorForDeviceScaleFactor(float zoom_factor_for_device_scale_factor)2356 void WebViewImpl::SetZoomFactorForDeviceScaleFactor(
2357 float zoom_factor_for_device_scale_factor) {
2358 DCHECK(does_composite_);
2359 // We can't early-return here if these are already equal, because we may
2360 // need to propagate the correct zoom factor to newly navigated frames.
2361 zoom_factor_for_device_scale_factor_ = zoom_factor_for_device_scale_factor;
2362 SetZoomLevel(zoom_level_);
2363 }
2364
SetPageLifecycleStateFromNewPageCommit(mojom::blink::PageVisibilityState visibility,mojom::blink::PagehideDispatch pagehide_dispatch)2365 void WebViewImpl::SetPageLifecycleStateFromNewPageCommit(
2366 mojom::blink::PageVisibilityState visibility,
2367 mojom::blink::PagehideDispatch pagehide_dispatch) {
2368 mojom::blink::PageLifecycleStatePtr state =
2369 GetPage()->GetPageLifecycleState().Clone();
2370 state->visibility = visibility;
2371 state->pagehide_dispatch = pagehide_dispatch;
2372 SetPageLifecycleStateInternal(std::move(state),
2373 /*page_restore_params=*/nullptr);
2374 }
2375
SetPageLifecycleState(mojom::blink::PageLifecycleStatePtr state,mojom::blink::PageRestoreParamsPtr page_restore_params,SetPageLifecycleStateCallback callback)2376 void WebViewImpl::SetPageLifecycleState(
2377 mojom::blink::PageLifecycleStatePtr state,
2378 mojom::blink::PageRestoreParamsPtr page_restore_params,
2379 SetPageLifecycleStateCallback callback) {
2380 SetPageLifecycleStateInternal(std::move(state),
2381 std::move(page_restore_params));
2382 // Tell the browser that the lifecycle update was successful.
2383 std::move(callback).Run();
2384 }
2385
SetPageLifecycleStateInternal(mojom::blink::PageLifecycleStatePtr new_state,mojom::blink::PageRestoreParamsPtr page_restore_params)2386 void WebViewImpl::SetPageLifecycleStateInternal(
2387 mojom::blink::PageLifecycleStatePtr new_state,
2388 mojom::blink::PageRestoreParamsPtr page_restore_params) {
2389 Page* page = GetPage();
2390 if (!page)
2391 return;
2392 auto& old_state = page->GetPageLifecycleState();
2393 bool storing_in_bfcache = new_state->is_in_back_forward_cache &&
2394 !old_state->is_in_back_forward_cache;
2395 bool restoring_from_bfcache = !new_state->is_in_back_forward_cache &&
2396 old_state->is_in_back_forward_cache;
2397 bool hiding_page =
2398 (new_state->visibility != mojom::blink::PageVisibilityState::kVisible) &&
2399 (old_state->visibility == mojom::blink::PageVisibilityState::kVisible);
2400 bool showing_page =
2401 (new_state->visibility == mojom::blink::PageVisibilityState::kVisible) &&
2402 (old_state->visibility != mojom::blink::PageVisibilityState::kVisible);
2403 bool freezing_page = new_state->is_frozen && !old_state->is_frozen;
2404 bool resuming_page = !new_state->is_frozen && old_state->is_frozen;
2405 bool dispatching_pagehide =
2406 (new_state->pagehide_dispatch !=
2407 mojom::blink::PagehideDispatch::kNotDispatched) &&
2408 !GetPage()->DispatchedPagehideAndStillHidden();
2409 bool dispatching_pageshow =
2410 (new_state->pagehide_dispatch ==
2411 mojom::blink::PagehideDispatch::kNotDispatched) &&
2412 GetPage()->DispatchedPagehideAndStillHidden();
2413
2414 if (dispatching_pagehide) {
2415 RemoveFocusAndTextInputState();
2416 }
2417 if (dispatching_pagehide) {
2418 // Note that |dispatching_pagehide| is different than |hiding_page|.
2419 // |dispatching_pagehide| will only be true when we're navigating away from
2420 // a page, while |hiding_page| might be true in other cases too such as when
2421 // the tab containing a page is backgrounded, and might be false even when
2422 // we're navigating away from a page, if the page is already hidden.
2423 DispatchPagehide(new_state->pagehide_dispatch);
2424 }
2425 if (hiding_page) {
2426 SetVisibilityState(new_state->visibility, /*is_initial_state=*/false);
2427 }
2428 if (storing_in_bfcache) {
2429 Scheduler()->SetPageBackForwardCached(new_state->is_in_back_forward_cache);
2430 }
2431 if (freezing_page)
2432 SetPageFrozen(true);
2433 if (storing_in_bfcache)
2434 HookBackForwardCacheEviction(true);
2435 if (restoring_from_bfcache) {
2436 DCHECK(page_restore_params);
2437 // Update the history offset and length value saved in RenderViewImpl, as
2438 // pages that are kept in the back-forward cache do not get notified about
2439 // updates on these values, so the currently saved value might be stale.
2440 web_view_client_->OnSetHistoryOffsetAndLength(
2441 page_restore_params->pending_history_list_offset,
2442 page_restore_params->current_history_list_length);
2443 HookBackForwardCacheEviction(false);
2444 }
2445 if (resuming_page)
2446 SetPageFrozen(false);
2447 if (showing_page) {
2448 SetVisibilityState(new_state->visibility, /*is_initial_state=*/false);
2449 }
2450 if (dispatching_pageshow) {
2451 DCHECK(restoring_from_bfcache);
2452 DispatchPageshow(page_restore_params->navigation_start);
2453 }
2454 if (restoring_from_bfcache) {
2455 DCHECK(dispatching_pageshow);
2456 DCHECK(page_restore_params);
2457 Scheduler()->SetPageBackForwardCached(new_state->is_in_back_forward_cache);
2458 }
2459
2460 // Make sure no TrackedFeaturesUpdate message is sent after the ACK
2461 // TODO(carlscab): Do we really need to go through LocalFrame =>
2462 // platform/scheduler/ => LocalFrame to report the features? We can probably
2463 // move SchedulerTrackedFeatures to core/ and remove the back and forth.
2464 ReportActiveSchedulerTrackedFeatures();
2465
2466 GetPage()->SetPageLifecycleState(std::move(new_state));
2467
2468 // Notify all local frames that we've updated the page lifecycle state.
2469 for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) {
2470 if (frame->IsWebLocalFrame()) {
2471 frame->ToWebLocalFrame()->Client()->DidSetPageLifecycleState();
2472 }
2473 }
2474 }
2475
ReportActiveSchedulerTrackedFeatures()2476 void WebViewImpl::ReportActiveSchedulerTrackedFeatures() {
2477 Page* page = GetPage();
2478 if (!page)
2479 return;
2480
2481 for (Frame* frame = page->MainFrame(); frame;
2482 frame = frame->Tree().TraverseNext()) {
2483 if (!frame->IsLocalFrame())
2484 continue;
2485 auto* local_frame = DynamicTo<LocalFrame>(frame);
2486 if (!local_frame->GetFrameScheduler())
2487 continue;
2488 local_frame->GetFrameScheduler()->ReportActiveSchedulerTrackedFeatures();
2489 }
2490 }
2491
AudioStateChanged(bool is_audio_playing)2492 void WebViewImpl::AudioStateChanged(bool is_audio_playing) {
2493 GetPage()->GetPageScheduler()->AudioStateChanged(is_audio_playing);
2494 }
2495
RemoveFocusAndTextInputState()2496 void WebViewImpl::RemoveFocusAndTextInputState() {
2497 auto& focus_controller = GetPage()->GetFocusController();
2498 auto* focused_frame = focus_controller.FocusedFrame();
2499 if (!focused_frame)
2500 return;
2501 // Remove focus from the currently focused element and frame.
2502 focus_controller.SetFocusedElement(nullptr, nullptr);
2503 // Clear composing state, and make sure we send a TextInputState update.
2504 // Note that the TextInputState itself is cleared when we clear the focus,
2505 // but no updates to the browser will be triggered until the next animation
2506 // frame, which won't happen if we're freezing the page.
2507 if (auto* widget = static_cast<WebFrameWidgetBase*>(
2508 focused_frame->GetWidgetForLocalRoot())) {
2509 widget->FinishComposingText(false /* keep_selection */);
2510 widget->UpdateTextInputState();
2511 }
2512 }
2513
DispatchPagehide(mojom::blink::PagehideDispatch pagehide_dispatch)2514 void WebViewImpl::DispatchPagehide(
2515 mojom::blink::PagehideDispatch pagehide_dispatch) {
2516 DCHECK_NE(pagehide_dispatch, mojom::blink::PagehideDispatch::kNotDispatched);
2517 bool persisted = (pagehide_dispatch ==
2518 mojom::blink::PagehideDispatch::kDispatchedPersisted);
2519 // Dispatch pagehide on all frames.
2520 for (Frame* frame = GetPage()->MainFrame(); frame;
2521 frame = frame->Tree().TraverseNext()) {
2522 if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
2523 frame->DomWindow()->ToLocalDOMWindow()->DispatchPagehideEvent(
2524 persisted
2525 ? PageTransitionEventPersistence::kPageTransitionEventPersisted
2526 : PageTransitionEventPersistence::
2527 kPageTransitionEventNotPersisted);
2528 }
2529 }
2530 }
2531
DispatchPageshow(base::TimeTicks navigation_start)2532 void WebViewImpl::DispatchPageshow(base::TimeTicks navigation_start) {
2533 for (Frame* frame = GetPage()->MainFrame(); frame;
2534 frame = frame->Tree().TraverseNext()) {
2535 auto* local_frame = DynamicTo<LocalFrame>(frame);
2536 // Record the metics.
2537 if (local_frame && local_frame->View()) {
2538 Document* document = local_frame->GetDocument();
2539 if (document) {
2540 PaintTiming::From(*document).OnRestoredFromBackForwardCache();
2541 InteractiveDetector::From(*document)->OnRestoredFromBackForwardCache();
2542 }
2543 DocumentLoader* loader = local_frame->Loader().GetDocumentLoader();
2544 if (loader) {
2545 loader->GetTiming().MarkBackForwardCacheRestoreNavigationStart(
2546 navigation_start);
2547 }
2548 }
2549 if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
2550 frame->DomWindow()->ToLocalDOMWindow()->DispatchPersistedPageshowEvent(
2551 navigation_start);
2552 if (frame->IsMainFrame()) {
2553 UMA_HISTOGRAM_BOOLEAN(
2554 "BackForwardCache.MainFrameHasPageshowListenersOnRestore",
2555 frame->DomWindow()->ToLocalDOMWindow()->HasEventListeners(
2556 event_type_names::kPageshow));
2557 }
2558 }
2559 }
2560 }
2561
HookBackForwardCacheEviction(bool hook)2562 void WebViewImpl::HookBackForwardCacheEviction(bool hook) {
2563 DCHECK(GetPage());
2564 for (Frame* frame = GetPage()->MainFrame(); frame;
2565 frame = frame->Tree().TraverseNext()) {
2566 auto* local_frame = DynamicTo<LocalFrame>(frame);
2567 if (!local_frame)
2568 continue;
2569 if (hook)
2570 local_frame->HookBackForwardCacheEviction();
2571 else
2572 local_frame->RemoveBackForwardCacheEviction();
2573 }
2574 }
2575
EnableAutoResizeMode(const gfx::Size & min_size,const gfx::Size & max_size)2576 void WebViewImpl::EnableAutoResizeMode(const gfx::Size& min_size,
2577 const gfx::Size& max_size) {
2578 should_auto_resize_ = true;
2579 min_auto_size_ = IntSize(min_size);
2580 max_auto_size_ = IntSize(max_size);
2581 ConfigureAutoResizeMode();
2582 }
2583
DisableAutoResizeMode()2584 void WebViewImpl::DisableAutoResizeMode() {
2585 should_auto_resize_ = false;
2586 ConfigureAutoResizeMode();
2587 }
2588
AutoResizeMode()2589 bool WebViewImpl::AutoResizeMode() {
2590 return should_auto_resize_;
2591 }
2592
EnableAutoResizeForTesting(const gfx::Size & min_window_size,const gfx::Size & max_window_size)2593 void WebViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_window_size,
2594 const gfx::Size& max_window_size) {
2595 EnableAutoResizeMode(web_widget_->DIPsToCeiledBlinkSpace(min_window_size),
2596 web_widget_->DIPsToCeiledBlinkSpace(max_window_size));
2597 }
2598
DisableAutoResizeForTesting(const gfx::Size & new_window_size)2599 void WebViewImpl::DisableAutoResizeForTesting(
2600 const gfx::Size& new_window_size) {
2601 if (!should_auto_resize_)
2602 return;
2603 DisableAutoResizeMode();
2604
2605 // The |new_size| is empty when resetting auto resize in between tests. In
2606 // this case the current size should just be preserved.
2607 if (!new_window_size.IsEmpty()) {
2608 web_widget_->Resize(web_widget_->DIPsToCeiledBlinkSpace(new_window_size));
2609 }
2610 }
2611
SetDefaultPageScaleLimits(float min_scale,float max_scale)2612 void WebViewImpl::SetDefaultPageScaleLimits(float min_scale, float max_scale) {
2613 GetPage()->SetDefaultPageScaleLimits(min_scale, max_scale);
2614 }
2615
SetInitialPageScaleOverride(float initial_page_scale_factor_override)2616 void WebViewImpl::SetInitialPageScaleOverride(
2617 float initial_page_scale_factor_override) {
2618 PageScaleConstraints constraints =
2619 GetPageScaleConstraintsSet().UserAgentConstraints();
2620 constraints.initial_scale = initial_page_scale_factor_override;
2621
2622 if (constraints == GetPageScaleConstraintsSet().UserAgentConstraints())
2623 return;
2624
2625 GetPageScaleConstraintsSet().SetNeedsReset(true);
2626 GetPage()->SetUserAgentPageScaleConstraints(constraints);
2627 }
2628
SetMaximumLegibleScale(float maximum_legible_scale)2629 void WebViewImpl::SetMaximumLegibleScale(float maximum_legible_scale) {
2630 maximum_legible_scale_ = maximum_legible_scale;
2631 }
2632
SetIgnoreViewportTagScaleLimits(bool ignore)2633 void WebViewImpl::SetIgnoreViewportTagScaleLimits(bool ignore) {
2634 PageScaleConstraints constraints =
2635 GetPageScaleConstraintsSet().UserAgentConstraints();
2636 if (ignore) {
2637 // Don't ignore the minimum limits in touchless mode to prevent wide
2638 // loading elements from causing us to zoom pages out beyond their layout
2639 // which is fairly common.
2640 if (!RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) {
2641 constraints.minimum_scale =
2642 GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale;
2643 }
2644 constraints.maximum_scale =
2645 GetPageScaleConstraintsSet().DefaultConstraints().maximum_scale;
2646 } else {
2647 if (!RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) {
2648 constraints.minimum_scale = -1;
2649 }
2650 constraints.maximum_scale = -1;
2651 }
2652 GetPage()->SetUserAgentPageScaleConstraints(constraints);
2653 }
2654
MainFrameSize()2655 IntSize WebViewImpl::MainFrameSize() {
2656 // The frame size should match the viewport size at minimum scale, since the
2657 // viewport must always be contained by the frame.
2658 return IntSize(gfx::ScaleToCeiledSize(size_, 1 / MinimumPageScaleFactor()));
2659 }
2660
GetPageScaleConstraintsSet() const2661 PageScaleConstraintsSet& WebViewImpl::GetPageScaleConstraintsSet() const {
2662 return GetPage()->GetPageScaleConstraintsSet();
2663 }
2664
RefreshPageScaleFactor()2665 void WebViewImpl::RefreshPageScaleFactor() {
2666 if (!MainFrame() || !GetPage() || !GetPage()->MainFrame() ||
2667 !GetPage()->MainFrame()->IsLocalFrame() ||
2668 !GetPage()->DeprecatedLocalMainFrame()->View())
2669 return;
2670 UpdatePageDefinedViewportConstraints(MainFrameImpl()
2671 ->GetFrame()
2672 ->GetDocument()
2673 ->GetViewportData()
2674 .GetViewportDescription());
2675 GetPageScaleConstraintsSet().ComputeFinalConstraints();
2676
2677 float new_page_scale_factor = PageScaleFactor();
2678 if (GetPageScaleConstraintsSet().NeedsReset() &&
2679 GetPageScaleConstraintsSet().FinalConstraints().initial_scale != -1) {
2680 new_page_scale_factor =
2681 GetPageScaleConstraintsSet().FinalConstraints().initial_scale;
2682 GetPageScaleConstraintsSet().SetNeedsReset(false);
2683 }
2684 SetPageScaleFactor(new_page_scale_factor);
2685
2686 // The constraints may have changed above which affects the page scale limits,
2687 // so we must update those even though SetPageScaleFactor() may do the same if
2688 // the scale factor is changed.
2689 if (does_composite_) {
2690 auto& viewport = GetPage()->GetVisualViewport();
2691 MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
2692 viewport.Scale(), viewport.IsPinchGestureActive(),
2693 MinimumPageScaleFactor(), MaximumPageScaleFactor());
2694 }
2695 }
2696
UpdatePageDefinedViewportConstraints(const ViewportDescription & description)2697 void WebViewImpl::UpdatePageDefinedViewportConstraints(
2698 const ViewportDescription& description) {
2699 if (!GetPage() || (!size_.width() && !size_.height()))
2700 return;
2701 // The viewport is a property of the main frame and its widget, so ignore it
2702 // when the main frame is remote.
2703 // TODO(danakj): Remove calls to this method from ChromeClient and DCHECK this
2704 // instead.
2705 if (!GetPage()->MainFrame()->IsLocalFrame())
2706 return;
2707
2708 if (!GetSettings()->ViewportEnabled()) {
2709 GetPageScaleConstraintsSet().ClearPageDefinedConstraints();
2710 UpdateMainFrameLayoutSize();
2711 return;
2712 }
2713
2714 Document* document = GetPage()->DeprecatedLocalMainFrame()->GetDocument();
2715
2716 Length default_min_width =
2717 document->GetViewportData().ViewportDefaultMinWidth();
2718 if (default_min_width.IsAuto())
2719 default_min_width = Length::ExtendToZoom();
2720
2721 float old_initial_scale =
2722 GetPageScaleConstraintsSet().PageDefinedConstraints().initial_scale;
2723 GetPageScaleConstraintsSet().UpdatePageDefinedConstraints(description,
2724 default_min_width);
2725
2726 if (SettingsImpl()->ClobberUserAgentInitialScaleQuirk() &&
2727 GetPageScaleConstraintsSet().UserAgentConstraints().initial_scale != -1 &&
2728 GetPageScaleConstraintsSet().UserAgentConstraints().initial_scale *
2729 DeviceScaleFactor() <=
2730 1) {
2731 if (description.max_width == Length::DeviceWidth() ||
2732 (description.max_width.IsAuto() &&
2733 GetPageScaleConstraintsSet().PageDefinedConstraints().initial_scale ==
2734 1.0f))
2735 SetInitialPageScaleOverride(-1);
2736 }
2737
2738 Settings& page_settings = GetPage()->GetSettings();
2739 GetPageScaleConstraintsSet().AdjustForAndroidWebViewQuirks(
2740 description, default_min_width.IntValue(), DeviceScaleFactor(),
2741 SettingsImpl()->SupportDeprecatedTargetDensityDPI(),
2742 page_settings.GetWideViewportQuirkEnabled(),
2743 page_settings.GetUseWideViewport(),
2744 page_settings.GetLoadWithOverviewMode(),
2745 SettingsImpl()->ViewportMetaNonUserScalableQuirk());
2746 float new_initial_scale =
2747 GetPageScaleConstraintsSet().PageDefinedConstraints().initial_scale;
2748 if (old_initial_scale != new_initial_scale && new_initial_scale != -1) {
2749 GetPageScaleConstraintsSet().SetNeedsReset(true);
2750 if (MainFrameImpl() && MainFrameImpl()->GetFrameView())
2751 MainFrameImpl()->GetFrameView()->SetNeedsLayout();
2752 }
2753
2754 UpdateMainFrameLayoutSize();
2755 }
2756
UpdateMainFrameLayoutSize()2757 void WebViewImpl::UpdateMainFrameLayoutSize() {
2758 if (should_auto_resize_ || !MainFrameImpl())
2759 return;
2760
2761 LocalFrameView* view = MainFrameImpl()->GetFrameView();
2762 if (!view)
2763 return;
2764
2765 gfx::Size layout_size = size_;
2766
2767 if (GetSettings()->ViewportEnabled())
2768 layout_size = gfx::Size(GetPageScaleConstraintsSet().GetLayoutSize());
2769
2770 if (GetPage()->GetSettings().GetForceZeroLayoutHeight())
2771 layout_size.set_height(0);
2772
2773 view->SetLayoutSize(IntSize(layout_size));
2774 }
2775
ContentsSize() const2776 IntSize WebViewImpl::ContentsSize() const {
2777 if (!GetPage()->MainFrame()->IsLocalFrame())
2778 return IntSize();
2779 auto* layout_view =
2780 GetPage()->DeprecatedLocalMainFrame()->ContentLayoutObject();
2781 if (!layout_view)
2782 return IntSize();
2783 return PixelSnappedIntRect(layout_view->DocumentRect()).Size();
2784 }
2785
ContentsPreferredMinimumSize()2786 gfx::Size WebViewImpl::ContentsPreferredMinimumSize() {
2787 DCHECK(page_->MainFrame()->IsLocalFrame());
2788
2789 auto* main_local_frame = DynamicTo<LocalFrame>(page_->MainFrame());
2790 Document* document = main_local_frame->GetDocument();
2791 if (!document || !document->GetLayoutView() || !document->documentElement() ||
2792 !document->documentElement()->GetLayoutBox())
2793 return gfx::Size();
2794
2795 // The preferred size requires an up-to-date layout tree.
2796 DCHECK(!document->NeedsLayoutTreeUpdate() &&
2797 !document->View()->NeedsLayout());
2798
2799 // Needed for computing MinPreferredWidth.
2800 FontCachePurgePreventer fontCachePurgePreventer;
2801 int width_scaled = document->GetLayoutView()
2802 ->PreferredLogicalWidths()
2803 .min_size.Round(); // Already accounts for zoom.
2804 int height_scaled =
2805 document->documentElement()->GetLayoutBox()->ScrollHeight().Round();
2806 return gfx::Size(width_scaled, height_scaled);
2807 }
2808
UpdatePreferredSize()2809 void WebViewImpl::UpdatePreferredSize() {
2810 // We don't always want to send the change messages over IPC, only if we've
2811 // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
2812 // message.
2813 if (!send_preferred_size_changes_ || !MainFrameImpl())
2814 return;
2815
2816 if (!needs_preferred_size_update_)
2817 return;
2818 needs_preferred_size_update_ = false;
2819
2820 gfx::Size size_in_dips =
2821 MainFrameImpl()->LocalRootFrameWidget()->BlinkSpaceToFlooredDIPs(
2822 gfx::Size(ContentsPreferredMinimumSize()));
2823
2824 if (size_in_dips != preferred_size_in_dips_) {
2825 preferred_size_in_dips_ = size_in_dips;
2826 local_main_frame_host_remote_->ContentsPreferredSizeChanged(size_in_dips);
2827 }
2828 }
2829
EnablePreferredSizeChangedMode()2830 void WebViewImpl::EnablePreferredSizeChangedMode() {
2831 if (send_preferred_size_changes_)
2832 return;
2833 send_preferred_size_changes_ = true;
2834 needs_preferred_size_update_ = true;
2835
2836 // We need to ensure |UpdatePreferredSize| gets called. If a layout is needed,
2837 // force an update here which will call |DidUpdateMainFrameLayout|.
2838 if (MainFrameWidget()) {
2839 MainFrameWidget()->UpdateLifecycle(WebLifecycleUpdate::kLayout,
2840 DocumentUpdateReason::kSizeChange);
2841 }
2842
2843 // If a layout was not needed, |DidUpdateMainFrameLayout| will not be called.
2844 // We explicitly update the preferred size here to ensure the preferred size
2845 // notification is sent.
2846 UpdatePreferredSize();
2847 }
2848
Focus()2849 void WebViewImpl::Focus() {
2850 if (GetPage()->MainFrame()->IsLocalFrame()) {
2851 DCHECK(local_main_frame_host_remote_);
2852 local_main_frame_host_remote_->FocusPage();
2853 } else {
2854 DCHECK(remote_main_frame_host_remote_);
2855 remote_main_frame_host_remote_->FocusPage();
2856 }
2857 }
2858
TakeFocus(bool reverse)2859 void WebViewImpl::TakeFocus(bool reverse) {
2860 if (GetPage()->MainFrame()->IsLocalFrame()) {
2861 DCHECK(local_main_frame_host_remote_);
2862 local_main_frame_host_remote_->TakeFocus(reverse);
2863 } else {
2864 DCHECK(remote_main_frame_host_remote_);
2865 remote_main_frame_host_remote_->TakeFocus(reverse);
2866 }
2867 }
2868
Show(const base::UnguessableToken & opener_frame_token,NavigationPolicy policy,const gfx::Rect & rect,bool opened_by_user_gesture)2869 void WebViewImpl::Show(const base::UnguessableToken& opener_frame_token,
2870 NavigationPolicy policy,
2871 const gfx::Rect& rect,
2872 bool opened_by_user_gesture) {
2873 // This is only called on local main frames.
2874 DCHECK(local_main_frame_host_remote_);
2875 DCHECK(web_widget_);
2876 web_widget_->SetPendingWindowRect(rect);
2877 local_main_frame_host_remote_->ShowCreatedWindow(
2878 opener_frame_token, NavigationPolicyToDisposition(policy), rect,
2879 opened_by_user_gesture,
2880 WTF::Bind(&WebViewImpl::DidShowCreatedWindow, WTF::Unretained(this)));
2881
2882 MainFrameDevToolsAgentImpl()->DidShowNewWindow();
2883 }
2884
DidShowCreatedWindow()2885 void WebViewImpl::DidShowCreatedWindow() {
2886 web_widget_->AckPendingWindowRect();
2887 }
2888
SetWindowRect(const gfx::Rect & bounds)2889 void WebViewImpl::SetWindowRect(const gfx::Rect& bounds) {
2890 DCHECK(local_main_frame_host_remote_);
2891 DCHECK(web_widget_);
2892 web_widget_->SetPendingWindowRect(bounds);
2893 local_main_frame_host_remote_->SetWindowRect(
2894 bounds, WTF::Bind(&WebViewImpl::DidSetWindowRect, WTF::Unretained(this)));
2895 }
2896
DidSetWindowRect()2897 void WebViewImpl::DidSetWindowRect() {
2898 web_widget_->AckPendingWindowRect();
2899 }
2900
UpdateTargetURL(const WebURL & url,const WebURL & fallback_url)2901 void WebViewImpl::UpdateTargetURL(const WebURL& url,
2902 const WebURL& fallback_url) {
2903 KURL latest_url = KURL(url.IsEmpty() ? fallback_url : url);
2904 if (latest_url == target_url_)
2905 return;
2906
2907 // Tell the browser to display a destination link.
2908 if (target_url_status_ == TARGET_INFLIGHT ||
2909 target_url_status_ == TARGET_PENDING) {
2910 // If we have a request in-flight, save the URL to be sent when we
2911 // receive an ACK to the in-flight request. We can happily overwrite
2912 // any existing pending sends.
2913 pending_target_url_ = latest_url;
2914 target_url_status_ = TARGET_PENDING;
2915 } else {
2916 // URLs larger than |kMaxURLChars| cannot be sent through IPC -
2917 // see |ParamTraits<GURL>|.
2918 if (latest_url.GetString().length() > url::kMaxURLChars)
2919 latest_url = KURL();
2920 SendUpdatedTargetURLToBrowser(latest_url);
2921 target_url_ = latest_url;
2922 target_url_status_ = TARGET_INFLIGHT;
2923 }
2924 }
2925
SendUpdatedTargetURLToBrowser(const KURL & target_url)2926 void WebViewImpl::SendUpdatedTargetURLToBrowser(const KURL& target_url) {
2927 // Note: WTF::Unretained() usage below is safe, since `this` owns both
2928 // `mojo::Remote` objects.
2929 if (GetPage()->MainFrame()->IsLocalFrame()) {
2930 DCHECK(local_main_frame_host_remote_);
2931 local_main_frame_host_remote_->UpdateTargetURL(
2932 target_url, WTF::Bind(&WebViewImpl::TargetURLUpdatedInBrowser,
2933 WTF::Unretained(this)));
2934 } else {
2935 DCHECK(remote_main_frame_host_remote_);
2936 remote_main_frame_host_remote_->UpdateTargetURL(
2937 target_url, WTF::Bind(&WebViewImpl::TargetURLUpdatedInBrowser,
2938 WTF::Unretained(this)));
2939 }
2940 }
2941
TargetURLUpdatedInBrowser()2942 void WebViewImpl::TargetURLUpdatedInBrowser() {
2943 // Check if there is a targeturl waiting to be sent.
2944 if (target_url_status_ == TARGET_PENDING)
2945 SendUpdatedTargetURLToBrowser(pending_target_url_);
2946
2947 target_url_status_ = TARGET_NONE;
2948 }
2949
DefaultMinimumPageScaleFactor() const2950 float WebViewImpl::DefaultMinimumPageScaleFactor() const {
2951 return GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale;
2952 }
2953
DefaultMaximumPageScaleFactor() const2954 float WebViewImpl::DefaultMaximumPageScaleFactor() const {
2955 return GetPageScaleConstraintsSet().DefaultConstraints().maximum_scale;
2956 }
2957
MinimumPageScaleFactor() const2958 float WebViewImpl::MinimumPageScaleFactor() const {
2959 return GetPageScaleConstraintsSet().FinalConstraints().minimum_scale;
2960 }
2961
MaximumPageScaleFactor() const2962 float WebViewImpl::MaximumPageScaleFactor() const {
2963 return GetPageScaleConstraintsSet().FinalConstraints().maximum_scale;
2964 }
2965
ResetScaleStateImmediately()2966 void WebViewImpl::ResetScaleStateImmediately() {
2967 GetPageScaleConstraintsSet().SetNeedsReset(true);
2968 }
2969
ResetScrollAndScaleState()2970 void WebViewImpl::ResetScrollAndScaleState() {
2971 GetPage()->GetVisualViewport().Reset();
2972
2973 auto* main_local_frame = DynamicTo<LocalFrame>(GetPage()->MainFrame());
2974 if (!main_local_frame)
2975 return;
2976
2977 if (LocalFrameView* frame_view = main_local_frame->View()) {
2978 ScrollableArea* scrollable_area = frame_view->LayoutViewport();
2979
2980 if (!scrollable_area->GetScrollOffset().IsZero()) {
2981 scrollable_area->SetScrollOffset(ScrollOffset(),
2982 mojom::blink::ScrollType::kProgrammatic);
2983 }
2984 }
2985
2986 if (Document* document = main_local_frame->GetDocument()) {
2987 if (DocumentLoader* loader = document->Loader()) {
2988 if (HistoryItem* item = loader->GetHistoryItem())
2989 item->ClearViewState();
2990 }
2991 }
2992
2993 GetPageScaleConstraintsSet().SetNeedsReset(true);
2994 }
2995
SendResizeEventForMainFrame()2996 void WebViewImpl::SendResizeEventForMainFrame() {
2997 // FIXME: This is wrong. The LocalFrameView is responsible sending a
2998 // resizeEvent as part of layout. Layout is also responsible for sending
2999 // invalidations to the embedder. This method and all callers may be wrong. --
3000 // eseidel.
3001 if (MainFrameImpl()->GetFrameView()) {
3002 // Enqueues the resize event.
3003 MainFrameImpl()->GetFrame()->GetDocument()->EnqueueResizeEvent();
3004 }
3005
3006 // A resized main frame can change the page scale limits.
3007 if (does_composite_) {
3008 auto& viewport = GetPage()->GetVisualViewport();
3009 MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
3010 viewport.Scale(), viewport.IsPinchGestureActive(),
3011 MinimumPageScaleFactor(), MaximumPageScaleFactor());
3012 }
3013 }
3014
ConfigureAutoResizeMode()3015 void WebViewImpl::ConfigureAutoResizeMode() {
3016 if (!MainFrameImpl() || !MainFrameImpl()->GetFrame() ||
3017 !MainFrameImpl()->GetFrame()->View())
3018 return;
3019
3020 if (should_auto_resize_) {
3021 MainFrameImpl()->GetFrame()->View()->EnableAutoSizeMode(min_auto_size_,
3022 max_auto_size_);
3023 } else {
3024 MainFrameImpl()->GetFrame()->View()->DisableAutoSizeMode();
3025 }
3026 }
3027
SetCompositorDeviceScaleFactorOverride(float device_scale_factor)3028 void WebViewImpl::SetCompositorDeviceScaleFactorOverride(
3029 float device_scale_factor) {
3030 if (compositor_device_scale_factor_override_ == device_scale_factor)
3031 return;
3032 compositor_device_scale_factor_override_ = device_scale_factor;
3033 if (zoom_factor_for_device_scale_factor_) {
3034 SetZoomLevel(ZoomLevel());
3035 return;
3036 }
3037 }
3038
SetDeviceEmulationTransform(const TransformationMatrix & transform)3039 void WebViewImpl::SetDeviceEmulationTransform(
3040 const TransformationMatrix& transform) {
3041 if (transform == device_emulation_transform_)
3042 return;
3043 device_emulation_transform_ = transform;
3044 UpdateDeviceEmulationTransform();
3045 }
3046
GetDeviceEmulationTransform() const3047 TransformationMatrix WebViewImpl::GetDeviceEmulationTransform() const {
3048 return device_emulation_transform_;
3049 }
3050
EnableDeviceEmulation(const DeviceEmulationParams & params)3051 void WebViewImpl::EnableDeviceEmulation(const DeviceEmulationParams& params) {
3052 web_widget_->EnableDeviceEmulation(params);
3053 }
3054
ActivateDevToolsTransform(const DeviceEmulationParams & params)3055 void WebViewImpl::ActivateDevToolsTransform(
3056 const DeviceEmulationParams& params) {
3057 TransformationMatrix device_emulation_transform =
3058 dev_tools_emulator_->EnableDeviceEmulation(params);
3059 SetDeviceEmulationTransform(device_emulation_transform);
3060 }
3061
DisableDeviceEmulation()3062 void WebViewImpl::DisableDeviceEmulation() {
3063 web_widget_->DisableDeviceEmulation();
3064 }
3065
DeactivateDevToolsTransform()3066 void WebViewImpl::DeactivateDevToolsTransform() {
3067 dev_tools_emulator_->DisableDeviceEmulation();
3068 SetDeviceEmulationTransform(TransformationMatrix());
3069 }
3070
PerformCustomContextMenuAction(unsigned action)3071 void WebViewImpl::PerformCustomContextMenuAction(unsigned action) {
3072 if (page_) {
3073 page_->GetContextMenuController().CustomContextMenuItemSelected(action);
3074 }
3075 }
3076
DidCloseContextMenu()3077 void WebViewImpl::DidCloseContextMenu() {
3078 LocalFrame* frame = page_->GetFocusController().FocusedFrame();
3079 if (frame)
3080 frame->Selection().SetCaretBlinkingSuspended(false);
3081 }
3082
BackgroundColor() const3083 SkColor WebViewImpl::BackgroundColor() const {
3084 if (background_color_override_enabled_)
3085 return background_color_override_;
3086 Page* page = page_.Get();
3087 if (!page)
3088 return BaseBackgroundColor().Rgb();
3089 if (auto* main_local_frame = DynamicTo<LocalFrame>(page->MainFrame())) {
3090 LocalFrameView* view = main_local_frame->View();
3091 if (view)
3092 return view->DocumentBackgroundColor().Rgb();
3093 }
3094 return BaseBackgroundColor().Rgb();
3095 }
3096
BaseBackgroundColor() const3097 Color WebViewImpl::BaseBackgroundColor() const {
3098 return base_background_color_override_enabled_
3099 ? base_background_color_override_
3100 : base_background_color_;
3101 }
3102
SetBaseBackgroundColor(SkColor color)3103 void WebViewImpl::SetBaseBackgroundColor(SkColor color) {
3104 if (base_background_color_ == color)
3105 return;
3106
3107 base_background_color_ = color;
3108 UpdateBaseBackgroundColor();
3109 }
3110
SetBaseBackgroundColorOverride(SkColor color)3111 void WebViewImpl::SetBaseBackgroundColorOverride(SkColor color) {
3112 if (base_background_color_override_enabled_ &&
3113 base_background_color_override_ == color) {
3114 return;
3115 }
3116
3117 base_background_color_override_enabled_ = true;
3118 base_background_color_override_ = color;
3119 if (MainFrameImpl()) {
3120 // Force lifecycle update to ensure we're good to call
3121 // LocalFrameView::setBaseBackgroundColor().
3122 MainFrameImpl()
3123 ->GetFrame()
3124 ->View()
3125 ->UpdateLifecycleToCompositingCleanPlusScrolling(
3126 DocumentUpdateReason::kBaseColor);
3127 }
3128 UpdateBaseBackgroundColor();
3129 }
3130
ClearBaseBackgroundColorOverride()3131 void WebViewImpl::ClearBaseBackgroundColorOverride() {
3132 if (!base_background_color_override_enabled_)
3133 return;
3134
3135 base_background_color_override_enabled_ = false;
3136 if (MainFrameImpl()) {
3137 // Force lifecycle update to ensure we're good to call
3138 // LocalFrameView::setBaseBackgroundColor().
3139 MainFrameImpl()
3140 ->GetFrame()
3141 ->View()
3142 ->UpdateLifecycleToCompositingCleanPlusScrolling(
3143 DocumentUpdateReason::kBaseColor);
3144 }
3145 UpdateBaseBackgroundColor();
3146 }
3147
UpdateBaseBackgroundColor()3148 void WebViewImpl::UpdateBaseBackgroundColor() {
3149 Color color = BaseBackgroundColor();
3150 if (auto* local_frame = DynamicTo<LocalFrame>(page_->MainFrame())) {
3151 LocalFrameView* view = local_frame->View();
3152 view->UpdateBaseBackgroundColorRecursively(color);
3153 }
3154 }
3155
UpdateFontRenderingFromRendererPrefs()3156 void WebViewImpl::UpdateFontRenderingFromRendererPrefs() {
3157 #if !defined(OS_MAC)
3158 skia::LegacyDisplayGlobals::SetCachedPixelGeometry(
3159 gfx::FontRenderParams::SubpixelRenderingToSkiaPixelGeometry(
3160 renderer_preferences_.subpixel_rendering));
3161 #if defined(OS_WIN)
3162 // Cache the system font metrics in blink.
3163 WebFontRendering::SetMenuFontMetrics(
3164 renderer_preferences_.menu_font_family_name.c_str(),
3165 renderer_preferences_.menu_font_height);
3166 WebFontRendering::SetSmallCaptionFontMetrics(
3167 renderer_preferences_.small_caption_font_family_name.c_str(),
3168 renderer_preferences_.small_caption_font_height);
3169 WebFontRendering::SetStatusFontMetrics(
3170 renderer_preferences_.status_font_family_name.c_str(),
3171 renderer_preferences_.status_font_height);
3172 WebFontRendering::SetAntialiasedTextEnabled(
3173 renderer_preferences_.should_antialias_text);
3174 WebFontRendering::SetLCDTextEnabled(
3175 renderer_preferences_.subpixel_rendering !=
3176 gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE);
3177 #else
3178 WebFontRenderStyle::SetHinting(
3179 RendererPreferencesToSkiaHinting(renderer_preferences_));
3180 WebFontRenderStyle::SetAutoHint(renderer_preferences_.use_autohinter);
3181 WebFontRenderStyle::SetUseBitmaps(renderer_preferences_.use_bitmaps);
3182 WebFontRenderStyle::SetAntiAlias(renderer_preferences_.should_antialias_text);
3183 WebFontRenderStyle::SetSubpixelRendering(
3184 renderer_preferences_.subpixel_rendering !=
3185 gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE);
3186 WebFontRenderStyle::SetSubpixelPositioning(
3187 renderer_preferences_.use_subpixel_positioning);
3188 #if (defined(OS_LINUX) && !defined(OS_ANDROID)) || defined(OS_BSD)
3189 if (!renderer_preferences_.system_font_family_name.empty()) {
3190 WebFontRenderStyle::SetSystemFontFamily(blink::WebString::FromUTF8(
3191 renderer_preferences_.system_font_family_name));
3192 }
3193 #endif // (defined(OS_LINUX) && !defined(OS_ANDROID)) || defined(OS_BSD)
3194 #endif // defined(OS_WIN)
3195 #endif // !defined(OS_MAC)
3196 }
3197
SetInsidePortal(bool inside_portal)3198 void WebViewImpl::SetInsidePortal(bool inside_portal) {
3199 GetPage()->SetInsidePortal(inside_portal);
3200
3201 // We may not have created the frame widget yet but that's ok because it'll
3202 // be created with this value correctly initialized. This can also be null if
3203 // the main frame is remote.
3204 if (web_widget_)
3205 web_widget_->SetIsNestedMainFrameWidget(inside_portal);
3206 }
3207
RegisterRendererPreferenceWatcher(CrossVariantMojoRemote<mojom::RendererPreferenceWatcherInterfaceBase> watcher)3208 void WebViewImpl::RegisterRendererPreferenceWatcher(
3209 CrossVariantMojoRemote<mojom::RendererPreferenceWatcherInterfaceBase>
3210 watcher) {
3211 renderer_preference_watchers_.Add(std::move(watcher));
3212 }
3213
SetRendererPreferences(const RendererPreferences & preferences)3214 void WebViewImpl::SetRendererPreferences(
3215 const RendererPreferences& preferences) {
3216 UpdateRendererPreferences(preferences);
3217 }
3218
GetRendererPreferences()3219 const RendererPreferences& WebViewImpl::GetRendererPreferences() {
3220 return renderer_preferences_;
3221 }
3222
UpdateRendererPreferences(const RendererPreferences & preferences)3223 void WebViewImpl::UpdateRendererPreferences(
3224 const RendererPreferences& preferences) {
3225 std::string old_accept_languages = renderer_preferences_.accept_languages;
3226 renderer_preferences_ = preferences;
3227
3228 for (auto& watcher : renderer_preference_watchers_)
3229 watcher->NotifyUpdate(renderer_preferences_);
3230
3231 // TODO(crbug.com/1102442): Remove once we no longer need to update theme
3232 // preferences on Windows via content::WebThemeEngineDefault.
3233 web_view_client_->DidUpdateRendererPreferences();
3234 UpdateFontRenderingFromRendererPrefs();
3235
3236 blink::SetCaretBlinkInterval(
3237 renderer_preferences_.caret_blink_interval.has_value()
3238 ? renderer_preferences_.caret_blink_interval.value()
3239 : base::TimeDelta::FromMilliseconds(
3240 mojom::blink::kDefaultCaretBlinkIntervalInMilliseconds));
3241
3242 #if defined(USE_AURA)
3243 if (renderer_preferences_.use_custom_colors) {
3244 SetFocusRingColor(renderer_preferences_.focus_ring_color);
3245 SetSelectionColors(renderer_preferences_.active_selection_bg_color,
3246 renderer_preferences_.active_selection_fg_color,
3247 renderer_preferences_.inactive_selection_bg_color,
3248 renderer_preferences_.inactive_selection_fg_color);
3249 ThemeChanged();
3250 }
3251 #endif
3252
3253 if (::features::IsFormControlsRefreshEnabled() &&
3254 renderer_preferences_.use_custom_colors) {
3255 SetFocusRingColor(renderer_preferences_.focus_ring_color);
3256 }
3257
3258 if (old_accept_languages != renderer_preferences_.accept_languages)
3259 AcceptLanguagesChanged();
3260
3261 GetSettings()->SetCaretBrowsingEnabled(
3262 renderer_preferences_.caret_browsing_enabled);
3263
3264 #if defined(USE_X11) || defined(USE_OZONE)
3265 GetSettings()->SetSelectionClipboardBufferAvailable(
3266 renderer_preferences_.selection_clipboard_buffer_available);
3267 #endif // defined(USE_X11) || defined(USE_OZONE)
3268 }
3269
SetHistoryOffsetAndLength(int32_t history_offset,int32_t history_length)3270 void WebViewImpl::SetHistoryOffsetAndLength(int32_t history_offset,
3271 int32_t history_length) {
3272 DCHECK(web_view_client_);
3273 web_view_client_->OnSetHistoryOffsetAndLength(history_offset, history_length);
3274 }
3275
SetWebPreferences(const web_pref::WebPreferences & preferences)3276 void WebViewImpl::SetWebPreferences(
3277 const web_pref::WebPreferences& preferences) {
3278 UpdateWebPreferences(preferences);
3279 }
3280
GetWebPreferences()3281 const web_pref::WebPreferences& WebViewImpl::GetWebPreferences() {
3282 return web_preferences_;
3283 }
3284
UpdateWebPreferences(const blink::web_pref::WebPreferences & preferences)3285 void WebViewImpl::UpdateWebPreferences(
3286 const blink::web_pref::WebPreferences& preferences) {
3287 web_preferences_ = preferences;
3288 ApplyWebPreferences(preferences, this);
3289 ApplyCommandLineToSettings(SettingsImpl());
3290 }
3291
SetIsActive(bool active)3292 void WebViewImpl::SetIsActive(bool active) {
3293 if (GetPage())
3294 GetPage()->GetFocusController().SetActive(active);
3295 }
3296
IsActive() const3297 bool WebViewImpl::IsActive() const {
3298 return GetPage() ? GetPage()->GetFocusController().IsActive() : false;
3299 }
3300
SetWindowFeatures(const WebWindowFeatures & features)3301 void WebViewImpl::SetWindowFeatures(const WebWindowFeatures& features) {
3302 page_->SetWindowFeatures(features);
3303 }
3304
SetOpenedByDOM()3305 void WebViewImpl::SetOpenedByDOM() {
3306 page_->SetOpenedByDOM();
3307 }
3308
DidCommitLoad(bool is_new_navigation,bool is_navigation_within_page)3309 void WebViewImpl::DidCommitLoad(bool is_new_navigation,
3310 bool is_navigation_within_page) {
3311 if (!is_navigation_within_page) {
3312 should_dispatch_first_visually_non_empty_layout_ = true;
3313 should_dispatch_first_layout_after_finished_parsing_ = true;
3314 should_dispatch_first_layout_after_finished_loading_ = true;
3315
3316 if (is_new_navigation)
3317 GetPageScaleConstraintsSet().SetNeedsReset(true);
3318 }
3319
3320 // Give the visual viewport's scroll layer its initial size.
3321 GetPage()->GetVisualViewport().MainFrameDidChangeSize();
3322 }
3323
ResizeAfterLayout()3324 void WebViewImpl::ResizeAfterLayout() {
3325 DCHECK(MainFrameImpl());
3326
3327 if (!web_view_client_ || !web_view_client_->CanUpdateLayout())
3328 return;
3329
3330 if (should_auto_resize_) {
3331 LocalFrameView* view = MainFrameImpl()->GetFrame()->View();
3332 gfx::Size frame_size = gfx::Size(view->Size());
3333 if (frame_size != size_) {
3334 size_ = frame_size;
3335
3336 GetPage()->GetVisualViewport().SetSize(IntSize(size_));
3337 GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(
3338 IntSize(size_));
3339 view->SetInitialViewportSize(IntSize(size_));
3340
3341 web_view_client_->DidAutoResize(size_);
3342 web_widget_->DidAutoResize(size_);
3343 SendResizeEventForMainFrame();
3344 }
3345 }
3346
3347 if (does_composite_ && GetPageScaleConstraintsSet().ConstraintsDirty())
3348 RefreshPageScaleFactor();
3349
3350 resize_viewport_anchor_->ResizeFrameView(MainFrameSize());
3351 }
3352
MainFrameLayoutUpdated()3353 void WebViewImpl::MainFrameLayoutUpdated() {
3354 DCHECK(MainFrameImpl());
3355 if (!web_view_client_)
3356 return;
3357
3358 web_view_client_->DidUpdateMainFrameLayout();
3359 needs_preferred_size_update_ = true;
3360 }
3361
DidChangeContentsSize()3362 void WebViewImpl::DidChangeContentsSize() {
3363 auto* local_frame = DynamicTo<LocalFrame>(GetPage()->MainFrame());
3364 if (!local_frame)
3365 return;
3366
3367 LocalFrameView* view = local_frame->View();
3368
3369 int vertical_scrollbar_width = 0;
3370 if (view && view->LayoutViewport()) {
3371 Scrollbar* vertical_scrollbar = view->LayoutViewport()->VerticalScrollbar();
3372 if (vertical_scrollbar && !vertical_scrollbar->IsOverlayScrollbar())
3373 vertical_scrollbar_width = vertical_scrollbar->Width();
3374 }
3375
3376 GetPageScaleConstraintsSet().DidChangeContentsSize(
3377 ContentsSize(), vertical_scrollbar_width, PageScaleFactor());
3378 }
3379
PageScaleFactorChanged()3380 void WebViewImpl::PageScaleFactorChanged() {
3381 // This is called from the VisualViewport which only is used to control the
3382 // page scale/scroll viewport for a local main frame, and only when
3383 // compositing as PageScaleFactor doesn't exist otherwise.
3384 DCHECK(MainFrameImpl());
3385 DCHECK(does_composite_);
3386
3387 GetPageScaleConstraintsSet().SetNeedsReset(false);
3388 // Set up the compositor and inform the browser of the PageScaleFactor,
3389 // which is tracked per-view.
3390 auto& viewport = GetPage()->GetVisualViewport();
3391 MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
3392 viewport.Scale(), viewport.IsPinchGestureActive(),
3393 MinimumPageScaleFactor(), MaximumPageScaleFactor());
3394
3395 local_main_frame_host_remote_->ScaleFactorChanged(viewport.Scale());
3396
3397 if (dev_tools_emulator_->HasViewportOverride()) {
3398 TransformationMatrix device_emulation_transform =
3399 dev_tools_emulator_->MainFrameScrollOrScaleChanged();
3400 SetDeviceEmulationTransform(device_emulation_transform);
3401 }
3402 }
3403
MainFrameScrollOffsetChanged()3404 void WebViewImpl::MainFrameScrollOffsetChanged() {
3405 DCHECK(MainFrameImpl());
3406 if (dev_tools_emulator_->HasViewportOverride()) {
3407 TransformationMatrix device_emulation_transform =
3408 dev_tools_emulator_->MainFrameScrollOrScaleChanged();
3409 SetDeviceEmulationTransform(device_emulation_transform);
3410 }
3411 }
3412
TextAutosizerPageInfoChanged(const mojom::blink::TextAutosizerPageInfo & page_info)3413 void WebViewImpl::TextAutosizerPageInfoChanged(
3414 const mojom::blink::TextAutosizerPageInfo& page_info) {
3415 DCHECK(MainFrameImpl());
3416 local_main_frame_host_remote_->TextAutosizerPageInfoChanged(
3417 page_info.Clone());
3418 }
3419
SetBackgroundColorOverride(SkColor color)3420 void WebViewImpl::SetBackgroundColorOverride(SkColor color) {
3421 DCHECK(does_composite_);
3422
3423 background_color_override_enabled_ = true;
3424 background_color_override_ = color;
3425 if (MainFrameImpl()) {
3426 MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor());
3427 }
3428 }
3429
ClearBackgroundColorOverride()3430 void WebViewImpl::ClearBackgroundColorOverride() {
3431 DCHECK(does_composite_);
3432
3433 background_color_override_enabled_ = false;
3434 if (MainFrameImpl()) {
3435 MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor());
3436 }
3437 }
3438
SetZoomFactorOverride(float zoom_factor)3439 void WebViewImpl::SetZoomFactorOverride(float zoom_factor) {
3440 zoom_factor_override_ = zoom_factor;
3441 SetZoomLevel(ZoomLevel());
3442 }
3443
FocusedElement() const3444 Element* WebViewImpl::FocusedElement() const {
3445 LocalFrame* frame = page_->GetFocusController().FocusedFrame();
3446 if (!frame)
3447 return nullptr;
3448
3449 Document* document = frame->GetDocument();
3450 if (!document)
3451 return nullptr;
3452
3453 return document->FocusedElement();
3454 }
3455
HitTestResultForTap(const gfx::Point & tap_point_window_pos,const gfx::Size & tap_area)3456 WebHitTestResult WebViewImpl::HitTestResultForTap(
3457 const gfx::Point& tap_point_window_pos,
3458 const gfx::Size& tap_area) {
3459 auto* main_frame = DynamicTo<LocalFrame>(page_->MainFrame());
3460 if (!main_frame)
3461 return HitTestResult();
3462
3463 WebGestureEvent tap_event(WebInputEvent::Type::kGestureTap,
3464 WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
3465 WebGestureDevice::kTouchscreen);
3466 // GestureTap is only ever from a touchscreen.
3467 tap_event.SetPositionInWidget(FloatPoint(IntPoint(tap_point_window_pos)));
3468 tap_event.data.tap.tap_count = 1;
3469 tap_event.data.tap.width = tap_area.width();
3470 tap_event.data.tap.height = tap_area.height();
3471
3472 WebGestureEvent scaled_event =
3473 TransformWebGestureEvent(MainFrameImpl()->GetFrameView(), tap_event);
3474
3475 HitTestResult result =
3476 main_frame->GetEventHandler()
3477 .HitTestResultForGestureEvent(
3478 scaled_event, HitTestRequest::kReadOnly | HitTestRequest::kActive)
3479 .GetHitTestResult();
3480
3481 result.SetToShadowHostIfInRestrictedShadowRoot();
3482 return result;
3483 }
3484
SetTabsToLinks(bool enable)3485 void WebViewImpl::SetTabsToLinks(bool enable) {
3486 tabs_to_links_ = enable;
3487 }
3488
TabsToLinks() const3489 bool WebViewImpl::TabsToLinks() const {
3490 return tabs_to_links_;
3491 }
3492
DidChangeRootLayer(bool root_layer_exists)3493 void WebViewImpl::DidChangeRootLayer(bool root_layer_exists) {
3494 if (!MainFrameImpl()) {
3495 DCHECK(!root_layer_exists);
3496 return;
3497 }
3498 if (root_layer_exists) {
3499 UpdateDeviceEmulationTransform();
3500 } else {
3501 // When the document in an already-attached main frame is being replaced by
3502 // a navigation then DidChangeRootLayer(false) will be called. Since we are
3503 // navigating, defer BeginMainFrames until the new document is ready for
3504 // them.
3505 //
3506 // TODO(crbug.com/936696): This should not be needed once we always swap
3507 // frames when swapping documents.
3508 scoped_defer_main_frame_update_ =
3509 MainFrameImpl()->FrameWidgetImpl()->DeferMainFrameUpdate();
3510 }
3511 }
3512
InvalidateRect(const IntRect & rect)3513 void WebViewImpl::InvalidateRect(const IntRect& rect) {
3514 // This is only for WebViewPlugin.
3515 if (!does_composite_ && web_view_client_)
3516 web_view_client_->DidInvalidateRect(rect);
3517 }
3518
ApplyViewportChanges(const ApplyViewportChangesArgs & args)3519 void WebViewImpl::ApplyViewportChanges(const ApplyViewportChangesArgs& args) {
3520 VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
3521
3522 // Store the desired offsets the visual viewport before setting the top
3523 // controls ratio since doing so will change the bounds and move the
3524 // viewports to keep the offsets valid. The compositor may have already
3525 // done that so we don't want to double apply the deltas here.
3526 FloatPoint visual_viewport_offset = visual_viewport.VisibleRect().Location();
3527 visual_viewport_offset.Move(args.inner_delta.x(), args.inner_delta.y());
3528
3529 GetBrowserControls().SetShownRatio(
3530 GetBrowserControls().TopShownRatio() + args.top_controls_delta,
3531 GetBrowserControls().BottomShownRatio() + args.bottom_controls_delta);
3532
3533 SetPageScaleFactorAndLocation(PageScaleFactor() * args.page_scale_delta,
3534 args.is_pinch_gesture_active,
3535 visual_viewport_offset);
3536
3537 if (args.page_scale_delta != 1) {
3538 double_tap_zoom_pending_ = false;
3539 visual_viewport.UserDidChangeScale();
3540 }
3541
3542 elastic_overscroll_ += FloatSize(args.elastic_overscroll_delta.x(),
3543 args.elastic_overscroll_delta.y());
3544 UpdateBrowserControlsConstraint(args.browser_controls_constraint);
3545
3546 if (args.scroll_gesture_did_end)
3547 MainFrameImpl()->GetFrame()->GetEventHandler().MarkHoverStateDirty();
3548 }
3549
RecordManipulationTypeCounts(cc::ManipulationInfo info)3550 void WebViewImpl::RecordManipulationTypeCounts(cc::ManipulationInfo info) {
3551 if (!MainFrameImpl())
3552 return;
3553
3554 if ((info & cc::kManipulationInfoWheel) == cc::kManipulationInfoWheel) {
3555 UseCounter::Count(MainFrameImpl()->GetDocument(),
3556 WebFeature::kScrollByWheel);
3557 }
3558 if ((info & cc::kManipulationInfoTouch) == cc::kManipulationInfoTouch) {
3559 UseCounter::Count(MainFrameImpl()->GetDocument(),
3560 WebFeature::kScrollByTouch);
3561 }
3562 if ((info & cc::kManipulationInfoPinchZoom) ==
3563 cc::kManipulationInfoPinchZoom) {
3564 UseCounter::Count(MainFrameImpl()->GetDocument(), WebFeature::kPinchZoom);
3565 }
3566 if ((info & cc::kManipulationInfoPrecisionTouchPad) ==
3567 cc::kManipulationInfoPrecisionTouchPad) {
3568 UseCounter::Count(MainFrameImpl()->GetDocument(),
3569 WebFeature::kScrollByPrecisionTouchPad);
3570 }
3571 }
3572
FindNodeFromScrollableCompositorElementId(cc::ElementId element_id) const3573 Node* WebViewImpl::FindNodeFromScrollableCompositorElementId(
3574 cc::ElementId element_id) const {
3575 if (!GetPage())
3576 return nullptr;
3577
3578 if (element_id == GetPage()->GetVisualViewport().GetScrollElementId()) {
3579 // Return the Document in this case since the window.visualViewport DOM
3580 // object is not a node.
3581 if (MainFrameImpl())
3582 return MainFrameImpl()->GetDocument();
3583 }
3584
3585 if (!GetPage()->GetScrollingCoordinator())
3586 return nullptr;
3587 ScrollableArea* scrollable_area =
3588 GetPage()
3589 ->GetScrollingCoordinator()
3590 ->ScrollableAreaWithElementIdInAllLocalFrames(element_id);
3591 if (!scrollable_area || !scrollable_area->GetLayoutBox())
3592 return nullptr;
3593
3594 return scrollable_area->GetLayoutBox()->GetNode();
3595 }
3596
UpdateDeviceEmulationTransform()3597 void WebViewImpl::UpdateDeviceEmulationTransform() {
3598 GetPage()->GetVisualViewport().SetNeedsPaintPropertyUpdate();
3599
3600 if (MainFrameImpl()) {
3601 // When the device emulation transform is updated, to avoid incorrect
3602 // scales and fuzzy raster from the compositor, force all content to
3603 // pick ideal raster scales.
3604 // TODO(wjmaclean): This is only done on the main frame's widget currently,
3605 // it should update all local frames.
3606 MainFrameImpl()->FrameWidgetImpl()->SetNeedsRecalculateRasterScales();
3607 }
3608 }
3609
Scheduler() const3610 PageScheduler* WebViewImpl::Scheduler() const {
3611 DCHECK(GetPage());
3612 return GetPage()->GetPageScheduler();
3613 }
3614
SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,bool is_initial_state)3615 void WebViewImpl::SetVisibilityState(
3616 mojom::blink::PageVisibilityState visibility_state,
3617 bool is_initial_state) {
3618 DCHECK(GetPage());
3619 if (!is_initial_state) {
3620 // Preserve the side effects of visibility change.
3621 web_view_client_->OnPageVisibilityChanged(visibility_state);
3622 }
3623 GetPage()->SetVisibilityState(visibility_state, is_initial_state);
3624 GetPage()->GetPageScheduler()->SetPageVisible(
3625 visibility_state == mojom::blink::PageVisibilityState::kVisible);
3626 }
3627
GetVisibilityState()3628 mojom::blink::PageVisibilityState WebViewImpl::GetVisibilityState() {
3629 DCHECK(GetPage());
3630 return GetPage()->GetVisibilityState();
3631 }
3632
DeviceScaleFactor() const3633 float WebViewImpl::DeviceScaleFactor() const {
3634 // TODO(oshima): Investigate if this should return the ScreenInfo's scale
3635 // factor rather than page's scale factor, which can be 1 in use-zoom-for-dsf
3636 // mode.
3637 if (!GetPage())
3638 return 1;
3639
3640 return GetPage()->DeviceScaleFactorDeprecated();
3641 }
3642
FocusedLocalFrameInWidget() const3643 LocalFrame* WebViewImpl::FocusedLocalFrameInWidget() const {
3644 if (!MainFrameImpl())
3645 return nullptr;
3646
3647 auto* focused_frame = To<LocalFrame>(FocusedCoreFrame());
3648 if (focused_frame->LocalFrameRoot() != MainFrameImpl()->GetFrame())
3649 return nullptr;
3650 return focused_frame;
3651 }
3652
FocusedLocalFrameAvailableForIme() const3653 LocalFrame* WebViewImpl::FocusedLocalFrameAvailableForIme() const {
3654 return ime_accept_events_ ? FocusedLocalFrameInWidget() : nullptr;
3655 }
3656
SetPageFrozen(bool frozen)3657 void WebViewImpl::SetPageFrozen(bool frozen) {
3658 Scheduler()->SetPageFrozen(frozen);
3659 web_view_client_->OnPageFrozenChanged(frozen);
3660 }
3661
MainFrameWidget()3662 WebFrameWidget* WebViewImpl::MainFrameWidget() {
3663 return web_widget_;
3664 }
3665
AddAutoplayFlags(int32_t value)3666 void WebViewImpl::AddAutoplayFlags(int32_t value) {
3667 page_->AddAutoplayFlags(value);
3668 }
3669
ClearAutoplayFlags()3670 void WebViewImpl::ClearAutoplayFlags() {
3671 page_->ClearAutoplayFlags();
3672 }
3673
AutoplayFlagsForTest()3674 int32_t WebViewImpl::AutoplayFlagsForTest() {
3675 return page_->AutoplayFlags();
3676 }
3677
GetPreferredSizeForTest()3678 gfx::Size WebViewImpl::GetPreferredSizeForTest() {
3679 return preferred_size_in_dips_;
3680 }
3681
StopDeferringMainFrameUpdate()3682 void WebViewImpl::StopDeferringMainFrameUpdate() {
3683 DCHECK(MainFrameImpl());
3684 scoped_defer_main_frame_update_ = nullptr;
3685 }
3686
SetDeviceColorSpaceForTesting(const gfx::ColorSpace & color_space)3687 void WebViewImpl::SetDeviceColorSpaceForTesting(
3688 const gfx::ColorSpace& color_space) {
3689 web_widget_->SetDeviceColorSpaceForTesting(color_space);
3690 }
3691
RunPaintBenchmark(int repeat_count,cc::PaintBenchmarkResult & result)3692 void WebViewImpl::RunPaintBenchmark(int repeat_count,
3693 cc::PaintBenchmarkResult& result) {
3694 DCHECK(MainFrameImpl());
3695 if (auto* frame_view = MainFrameImpl()->GetFrameView())
3696 frame_view->RunPaintBenchmark(repeat_count, result);
3697 }
3698
3699 } // namespace blink
3700