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