diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/content/renderer | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/renderer')
133 files changed, 5018 insertions, 5727 deletions
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn index 12e9157d582..4f85483915e 100644 --- a/chromium/content/renderer/BUILD.gn +++ b/chromium/content/renderer/BUILD.gn @@ -37,6 +37,8 @@ target(link_target_type, "renderer") { "accessibility/ax_action_target_factory.h", "accessibility/ax_image_annotator.cc", "accessibility/ax_image_annotator.h", + "accessibility/ax_image_stopwords.cc", + "accessibility/ax_image_stopwords.h", "accessibility/blink_ax_action_target.cc", "accessibility/blink_ax_action_target.h", "accessibility/blink_ax_tree_source.cc", @@ -45,8 +47,8 @@ target(link_target_type, "renderer") { "accessibility/render_accessibility_impl.h", "accessibility/render_accessibility_manager.cc", "accessibility/render_accessibility_manager.h", - "android/synchronous_layer_tree_frame_sink.cc", - "android/synchronous_layer_tree_frame_sink.h", + "android/synchronous_layer_tree_frame_sink_impl.cc", + "android/synchronous_layer_tree_frame_sink_impl.h", "browser_exposed_renderer_interfaces.cc", "browser_exposed_renderer_interfaces.h", "categorized_worker_pool.cc", @@ -98,9 +100,6 @@ target(link_target_type, "renderer") { "input/main_thread_event_queue_task.h", "input/main_thread_event_queue_task_list.cc", "input/main_thread_event_queue_task_list.h", - "input/render_widget_input_handler.cc", - "input/render_widget_input_handler.h", - "input/render_widget_input_handler_delegate.h", "input/widget_input_handler_impl.cc", "input/widget_input_handler_impl.h", "input/widget_input_handler_manager.cc", @@ -147,8 +146,6 @@ target(link_target_type, "renderer") { "loader/web_url_request_util.h", "loader/web_worker_fetch_context_impl.cc", "loader/web_worker_fetch_context_impl.h", - "low_memory_mode_controller.cc", - "low_memory_mode_controller.h", "media/android/flinging_renderer_client.cc", "media/android/flinging_renderer_client.h", "media/android/flinging_renderer_client_factory.cc", @@ -214,6 +211,8 @@ target(link_target_type, "renderer") { "navigation_state.h", "net_info_helper.cc", "net_info_helper.h", + "performance_manager/v8_per_frame_memory_reporter_impl.cc", + "performance_manager/v8_per_frame_memory_reporter_impl.h", "peripheral_content_heuristic.cc", "peripheral_content_heuristic.h", "queue_message_swap_promise.cc", @@ -252,8 +251,6 @@ target(link_target_type, "renderer") { "renderer_main_platform_delegate_win.cc", "sad_plugin.cc", "sad_plugin.h", - "savable_resources.cc", - "savable_resources.h", "seccomp_sandbox_status_android.cc", "seccomp_sandbox_status_android.h", "service_worker/controller_service_worker_connector.cc", @@ -332,6 +329,7 @@ target(link_target_type, "renderer") { deps = [ "//base", "//base:i18n", + "//build:chromecast_buildflags", "//cc", "//cc/animation", "//cc/mojo_embedder", @@ -373,7 +371,6 @@ target(link_target_type, "renderer") { "//media/mojo:buildflags", "//media/mojo/clients", "//media/mojo/mojom", - "//media/mojo/mojom:remoting", "//media/webrtc", "//mojo/public/cpp/bindings", "//net", @@ -387,6 +384,7 @@ target(link_target_type, "renderer") { "//services/image_annotation/public/cpp:cpp", "//services/image_annotation/public/mojom:mojom", "//services/metrics/public/cpp:metrics_cpp", + "//services/metrics/public/cpp:ukm_builders", "//services/network:network_service", "//services/service_manager/public/cpp", "//services/service_manager/public/mojom", @@ -406,7 +404,7 @@ target(link_target_type, "renderer") { "//ui/accessibility", "//ui/base", "//ui/base/clipboard", - "//ui/base/cursor", + "//ui/base/cursor:cursor_base", "//ui/base/ime", "//ui/display", "//ui/events:dom_keycode_converter", @@ -427,6 +425,7 @@ target(link_target_type, "renderer") { "input/synchronous_compositor_proxy.cc", "input/synchronous_compositor_proxy.h", "input/synchronous_compositor_registry.h", + "input/synchronous_layer_tree_frame_sink.h", # Add back the Linux file which Android shares. "render_view_linux.cc", @@ -454,10 +453,7 @@ target(link_target_type, "renderer") { } if (is_linux) { - deps += [ - "//components/services/font/public/cpp", - "//services/service_manager/zygote", - ] + deps += [ "//components/services/font/public/cpp" ] } if (is_mac) { @@ -484,8 +480,19 @@ target(link_target_type, "renderer") { ] } - if (enable_media_remoting) { - deps += [ "//media/remoting" ] + if (enable_media_remoting || is_chromecast) { + deps += [ "//media/mojo/mojom:remoting" ] + + if (enable_media_remoting) { + deps += [ "//media/remoting:remoting_sender" ] + } + + if (is_chromecast) { + deps += [ + "//media/remoting:remoting_constants", + "//media/remoting:remoting_renderer", + ] + } } if (enable_plugins) { @@ -642,7 +649,7 @@ target(link_target_type, "renderer") { "//printing/mojom", "//third_party/libvpx", "//third_party/opus", - "//ui/base/cursor", + "//ui/base/cursor:cursor_base", "//ui/base/cursor/mojom:cursor_type", ] } diff --git a/chromium/content/renderer/accessibility/aom_content_ax_tree.cc b/chromium/content/renderer/accessibility/aom_content_ax_tree.cc index 4bce29368ff..67f9ebc0a04 100644 --- a/chromium/content/renderer/accessibility/aom_content_ax_tree.cc +++ b/chromium/content/renderer/accessibility/aom_content_ax_tree.cc @@ -7,6 +7,7 @@ #include <string> #include "content/common/ax_content_node_data.h" +#include "content/common/ax_content_tree_update.h" #include "content/renderer/accessibility/render_accessibility_impl.h" #include "third_party/blink/public/web/web_ax_enums.h" #include "ui/accessibility/ax_enum_util.h" diff --git a/chromium/content/renderer/accessibility/ax_image_annotator.cc b/chromium/content/renderer/accessibility/ax_image_annotator.cc index 3a38e7be07f..ffff4842975 100644 --- a/chromium/content/renderer/accessibility/ax_image_annotator.cc +++ b/chromium/content/renderer/accessibility/ax_image_annotator.cc @@ -9,10 +9,13 @@ #include <vector> #include "base/base64.h" +#include "base/i18n/char_iterator.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "content/public/common/content_client.h" +#include "content/renderer/accessibility/ax_image_stopwords.h" #include "content/renderer/render_frame_impl.h" #include "crypto/sha2.h" #include "third_party/blink/public/strings/grit/blink_strings.h" @@ -21,6 +24,7 @@ #include "third_party/blink/public/web/web_element.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_node.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/gfx/geometry/size.h" #include "url/gurl.h" @@ -114,6 +118,34 @@ void AXImageAnnotator::OnImageRemoved(blink::WebAXObject& image) { image_annotations_.erase(lookup); } +// static +bool AXImageAnnotator::ImageNameHasMostlyStopwords( + const std::string& image_name) { + // Split the image name into words by splitting on all whitespace and + // punctuation. Reject any words that are classified as stopwords. + // If there are 3 or fewer unicode codepoints remaining, classify + // the string as "mostly stopwords". + // + // More details and analysis in this (Google-internal) design doc: + // http://goto.google.com/augment-existing-image-descriptions + const char* separators = "0123456789`~!@#$%^&*()[]{}\\|;:'\",.<>?/-_=+ "; + std::vector<std::string> words = base::SplitString( + image_name, separators, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + int remaining_codepoints = 0; + for (const std::string& word : words) { + if (AXImageStopwords::GetInstance().IsImageStopword(word.c_str())) + continue; + + base::i18n::UTF8CharIterator iter(&word); + while (!iter.end()) { + remaining_codepoints++; + iter.Advance(); + } + } + + return (remaining_codepoints <= 3); +} + #if defined(CONTENT_IMPLEMENTATION) ContentClient* AXImageAnnotator::GetContentClient() const { return content::GetContentClient(); diff --git a/chromium/content/renderer/accessibility/ax_image_annotator.h b/chromium/content/renderer/accessibility/ax_image_annotator.h index fcc1a316106..88a3069d280 100644 --- a/chromium/content/renderer/accessibility/ax_image_annotator.h +++ b/chromium/content/renderer/accessibility/ax_image_annotator.h @@ -55,6 +55,8 @@ class CONTENT_EXPORT AXImageAnnotator : public base::CheckedObserver { void OnImageUpdated(blink::WebAXObject& image); void OnImageRemoved(blink::WebAXObject& image); + static bool ImageNameHasMostlyStopwords(const std::string& image_name); + private: // Keeps track of the image data and the automatic annotation for each image. class ImageInfo final { diff --git a/chromium/content/renderer/accessibility/ax_image_stopwords.cc b/chromium/content/renderer/accessibility/ax_image_stopwords.cc new file mode 100644 index 00000000000..d563264bda1 --- /dev/null +++ b/chromium/content/renderer/accessibility/ax_image_stopwords.cc @@ -0,0 +1,575 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#include "base/containers/flat_set.h" +#include "base/i18n/case_conversion.h" +#include "base/i18n/char_iterator.h" +#include "base/no_destructor.h" +#include "base/stl_util.h" +#include "base/strings/string16.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_split.h" +#include "base/strings/utf_string_conversions.h" +#include "content/renderer/accessibility/ax_image_stopwords.h" +#include "third_party/icu/source/common/unicode/uchar.h" + +namespace content { + +namespace { + +// List of image stopwords for all languages. See ax_image_stopwords.h +// for information about how image stopwords are defined and how they're +// used. +// +// The stopwords are encoded here as a single long string delimited by +// newlines. This is much more efficient than an array of strings, which +// in practice takes ~6x more storage in the resulting binary. +// +// Current size as of June 2020: +// 369 unique words +// 2542 bytes uncompressed +// 1127 bytes gzipped +const char kImageStopwordsUtf8[] = { + // + // Language-independent stopwords. + // + + "com\n" + "edu\n" + "http\n" + "https\n" + "www\n" + + // + // English. + // + + // General English stopwords. + "and\n" + "are\n" + "for\n" + "from\n" + "how\n" + "online\n" + "our\n" + "the\n" + "this\n" + "with\n" + "you\n" + "your\n" + + // English image-specific stopwords. + "art\n" + "avatar\n" + "background\n" + "backgrounds\n" + "black\n" + "download\n" + "drawing\n" + "drawings\n" + "free\n" + "gif\n" + "icon\n" + "icons\n" + "illustration\n" + "illustrations\n" + "image\n" + "images\n" + "jpeg\n" + "jpg\n" + "logo\n" + "logos\n" + "meme\n" + "memes\n" + "photo\n" + "photos\n" + "picture\n" + "pictures\n" + "png\n" + "stock\n" + "transparent\n" + "vector\n" + "vectors\n" + "video\n" + "videos\n" + "wallpaper\n" + "wallpapers\n" + "white\n" + + // Alt text from may images starts with "Image may contain". + "may\n" + "contain\n" + + // Many images on the web have the alt text "Highlights info row." + "highlights\n" + "info\n" + "row\n" + + // Google Photos images are labeled as "portrait" or "landscape". + "portrait\n" + "landscape\n" + + // Reddit says "post image". + "post\n" + + // Months and month abbreviations. Often used as part of the date/time + // when a photograph was taken. + "january\n" + "jan\n" + "february\n" + "feb\n" + "march\n" + "mar\n" + "april\n" + "apr\n" + "may\n" + "june\n" + "jun\n" + "july\n" + "jul\n" + "august\n" + "aug\n" + "september\n" + "sep\n" + "october\n" + "oct" + "november" + "nov\n" + "december\n" + "dec\n" + + // Days of the week. + "monday\n" + "mon\n" + "tuesday\n" + "tue\n" + "wednesday\n" + "wed\n" + "thursday\n" + "thu\n" + "friday\n" + "fri\n" + "saturday\n" + "sat\n" + "sunday\n" + "sun\n" + + // + // French + // + + // General French stopwords. + "les\n" // the + "pour\n" // for + "des\n" // of the + "sur\n" // on + "avec\n" // with + "une\n" // one + "dans\n" // in + "est\n" // is + "plus\n" // more + "par\n" // by + "vous\n" // you + "pas\n" // not + "qui\n" // who + "aux\n" // to the + "son\n" // his/her/its + "nous\n" // we + "voir\n" // see + + // French Image stopwords. + "noir\n" // black + "blanc\n" // white + "dessin\n" // drawing + "font\n" // background + "peinture\n" // painting + + // Months. + "janvier\n" + "janv\n" + "février\n" + "févr\n" + "mars\n" + "avril\n" + "mai\n" + "juin\n" + "juillet\n" + "juil\n" + "août\n" + "septembre\n" + "sept\n" + "octobre\n" + "oct\n" + "novembre\n" + "nov\n" + "décembre\n" + "déc\n" + + // Days of the week. + "lundi\n" + "lun\n" + "mardi\n" + "mar\n" + "mercredi\n" + "mer\n" + "jeudi\n" + "jeu\n" + "vendredi\n" + "ven\n" + "samedi\n" + "sam\n" + "dimanche\n" + "dim\n" + + // + // Italian + // + + "con\n" // with + "per\n" // through, by + "non\n" // not + "come\n" // as + "più\n" // more + "dal\n" // da + il + "dallo\n" // da + lo + "dai\n" // da + i + "dagli\n" // da + gli + "dall\n" // da + l' + "dagl\n" // da + gll' + "dalla\n" // da + la + "dalle\n" // da + le + "del\n" // di + il + "dello\n" // di + lo + "dei\n" // di + i + "degli\n" // di + gli + "dell\n" // di + l' + "degl\n" // di + gl' + "della\n" // di + la + "delle\n" // di + le + "nel\n" // in + el + "nello\n" // in + lo + "nei\n" // in + i + "negli\n" // in + gli + "nell\n" // in + l' + "negl\n" // in + gl' + "nella\n" // in + la + "nelle\n" // in + le + "sul\n" // su + il + "sullo\n" // su + lo + "sui\n" // su + i + "sugli\n" // su + gli + "sull\n" // su + l' + "sugl\n" // su + gl' + "sulla\n" // su + la + "sulle\n" // su + le + + // Images + "arte\n" + "immagini\n" + "illustrazione\n" + "fotografia\n" + "icona\n" + + "bianca\n" // white + "bianco\n" // white + "nera\n" // black + "nero\n" // black + "contenere\n" // contain (image may contain...) + + // Months. + "gennaio\n" + "genn\n" + "febbraio\n" + "febbr\n" + "marzo\n" + "mar\n" + "aprile\n" + "apr\n" + "maggio\n" + "magg\n" + "giugno\n" + "luglio\n" + "agosto\n" + "settembre\n" + "sett\n" + "ottobre\n" + "ott\n" + "novembre\n" + "nov\n" + "dicembre\n" + "dic\n" + + // Weekdays. + "lunedì\n" + "lun\n" + "martedì\n" + "mar\n" + "mercoledì\n" + "mer\n" + "giovedì\n" + "gio\n" + "venerdì\n" + "ven\n" + "sabato\n" + "sab\n" + "domenica\n" + "dom\n" + + // + // German + // + + // General German stopwords. + "und\n" // and + "mit\n" // with + "für\n" // for + "der\n" // the + "die\n" // the + "von\n" // of, from + "auf\n" // on + "das\n" // the + "aus\n" // out of + "ist\n" // is + "ein\n" // one + "eine\n" // one + "sie\n" // they, she + "den\n" // the + "zum\n" // zu + dem + "zur\n" // zu + der + "bei\n" // by + "des\n" // the + "sprüche\n" // claims (to be) + "oder\n" // or + + // German Image stopwords. + "bild\n" // picture + "bilder\n" // pictures + "foto\n" // photo + "schwarz\n" // black + "weiß\n" // white + + // Months. + "januar\n" + "jan\n" + "jän\n" + "februar\n" + "feb\n" + "märz\n" + "april\n" + "apr\n" + "mai\n" + "juni\n" + "juli\n" + "august\n" + "aug\n" + "september\n" + "sept\n" + "oktober\n" + "okt\n" + "november\n" + "nov\n" + "dezember\n" + "dez\n" + + // Weekdays. + "montag\n" + "dienstag\n" + "mittwoch\n" + "donnerstag\n" + "freitag\n" + "samstag\n" + "sonntag\n" + + // + // Spanish + // + + // General Spanish stopwords. + "con\n" // with + "para\n" // by + "del\n" // of the + "que\n" // that + "los\n" // the + "las\n" // the + "una\n" // one + "por\n" // for + "más\n" // more + "como\n" // how + + // Spanish image stopwords. + "dibujos\n" // drawings + "imagen\n" // images + "arte\n" // art + "fondo\n" // background + "fondos\n" // backgrounds + "diseño\n" // design + "ilustración\n" // illustration + "imagenes\n" // images + "blanca\n" // white + "blanco\n" // white + "negra\n" // black + "negro\n" // black + + // Months. + "enero\n" + "febrero\n" + "feb\n" + "marzo\n" + "abril\n" + "abr\n" + "mayo\n" + "junio\n" + "jun\n" + "julio\n" + "jul\n" + "agosto\n" + "septiembre\n" + "sept\n" + "set\n" + "octubre\n" + "oct\n" + "noviembre\n" + "nov\n" + "diciembre\n" + "dic\n" + + // Weekdays. Weekday abbreviations in Spanish are two-letters which + // don't need to be listed here (anything less than 3 letters is + // considered a stopword already). + "lunes\n" + "martes\n" + "miércoles\n" + "jueves\n" + "viernes\n" + "sábado\n" + "domingo\n" + + // + // Hindi + // + + // General Hindi stopwords. + "में\n" // in + "लिए\n" // for + "नहीं\n" // no + "एक\n" // one + "साथ\n" // with + "दिया\n" // gave + "किया\n" // did + "रहे\n" // are + "सकता\n" // can + "इस\n" // this + "शामिल\n" // include + "तारीख\n" // the date + + // Hindi image stopwords. + "चित्र\n" // picture + "वीडियो\n" // video + + // Months + "जनवरी\n" + "फरवरी\n" + "मार्च\n" + "अप्रैल\n" + "मई\n" + "जून\n" + "जुलाई\n" + "अगस्त\n" + "सितंबर\n" + "अक्टूबर\n" + "नवंबर\n" + "दिसंबर\n" + + // Weekdays. + "सोमवार\n" + "मंगलवार\n" + "बुधवार\n" + "बृहस्पतिवार\n" + "शुक्रवार\n" + "शनिवार\n" + "रविवार\n"}; + +} // namespace + +// static +AXImageStopwords& AXImageStopwords::GetInstance() { + static base::NoDestructor<AXImageStopwords> instance; + return *instance; +} + +AXImageStopwords::AXImageStopwords() { + // Parse the newline-delimited stopwords from kImageStopwordsUtf8 and store + // them as a flat_set of type StringPiece. This is very memory-efficient + // because it avoids ever needing to copy any of the strings; each StringPiece + // is just a pointer into kImageStopwordsUtf8 and flat_set acts like a set but + // basically just does a binary search. + std::vector<base::StringPiece> stopwords = + base::SplitStringPiece(kImageStopwordsUtf8, "\n", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + + // It's inefficient to add things to a flat_set one at a time. Copy them + // all over at once. + stopword_set_ = stopwords; +} + +AXImageStopwords::~AXImageStopwords() = default; + +bool AXImageStopwords::IsImageStopword(const char* word_utf8) const { + base::string16 word_utf16 = base::UTF8ToUTF16(word_utf8); + + // It's not really meaningful, but since short words are stopwords, for + // simplicity we define the empty string to be a stopword too. + if (word_utf16.empty()) + return true; + + // Canonicalize case, this is like "ToLower" for many languages but + // works independently of the current locale. + word_utf16 = base::i18n::FoldCase(word_utf16); + + // Count the number of distinct codepoints from a supported unicode block. + base::i18n::UTF16CharIterator iter(&word_utf16); + int supported_count = 0; + int total_count = 0; + while (!iter.end()) { + total_count++; + int32_t codepoint = iter.get(); + UBlockCode block_code = ublock_getCode(codepoint); + switch (block_code) { + case UBLOCK_BASIC_LATIN: + case UBLOCK_LATIN_1_SUPPLEMENT: + case UBLOCK_LATIN_EXTENDED_A: + case UBLOCK_DEVANAGARI: + supported_count++; + break; + default: + break; + } + iter.Advance(); + } + + // Treat any string of 2 or fewer characters in any of these unicode + // blocks as a stopword. Of course, there are rare exceptions, but they're + // acceptable for this heuristic. All that means is that we won't count + // those words when trying to determine if the alt text for an image + // has meaningful text or not. The odds are good that a 1 or 2 character + // word is not meaningful. + // + // Note: this assumption might not be valid for some unicode blocks, + // like Chinese. That's why the heuristic only applies to certain unicode + // blocks where we believe this to be a reasonable assumption. + // + // Note that in Devanagari (the script used for the Hindi language, among + // others) a word sometimes looks like a single character (one glyph) but it's + // actually two or more unicode codepoints (consonants and vowels that are + // joined together), which is why this heuristic still works. Anything with + // two or fewer unicode codepoints is an extremely short word. + if (supported_count == total_count && total_count <= 2) + return true; + + return base::Contains(stopword_set_, base::UTF16ToUTF8(word_utf16)); +} + +} // namespace content diff --git a/chromium/content/renderer/accessibility/ax_image_stopwords.h b/chromium/content/renderer/accessibility/ax_image_stopwords.h new file mode 100644 index 00000000000..2a6239867d1 --- /dev/null +++ b/chromium/content/renderer/accessibility/ax_image_stopwords.h @@ -0,0 +1,71 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_ACCESSIBILITY_AX_IMAGE_STOPWORDS_H_ +#define CONTENT_RENDERER_ACCESSIBILITY_AX_IMAGE_STOPWORDS_H_ + +#include "base/containers/flat_set.h" +#include "base/no_destructor.h" +#include "base/stl_util.h" +#include "base/strings/string_piece.h" +#include "content/common/content_export.h" + +namespace content { + +// Maintains a set of image stopwords and provides a function to check +// whether or not a given word is an image stopword. +// +// A stopword in general is a word that's filtered out before doing +// natural language processing. In English, common stopwords include +// "the" or "of" - they are words that are part of grammatically correct +// sentences but don't add any useful semantics themselves. +// +// This set is used as part of an algorithm to determine whether the +// accessible label for an image (including the "alt" attribute and +// other attributes) contains a useful description or not. For this +// application, both common stopwords like "the", but also image-related +// words like "image" and "photo" are included, because an image that's +// just labeled with the word "photo" is essentially unlabeled. +// +// Stopwords from all supported languages are grouped together, because +// it's simpler to just have one set rather than to try to split by the +// element language (which is sometimes wrong). This leads to a small +// but acceptable number of false positives if a stopword in one language +// is a meaningful word in another language. +// +// The set of supported languages should include all of the languages +// that we can generate automatic image descriptions for. This will grow +// over time. +// +// Words consisting of just one or two characters made up of letters from +// Latin alphabets are always considered stopwords, but that doesn't +// generalize to all languages / character sets. +// +// The set of stopwords was obtained by extracting the alt text of images +// from billions of web pages, tokenizing, counting, and then manually +// categorizing the top words, with the help of dictionaries and language +// experts. More details in this (Google-internal) design doc: +// http://goto.google.com/augment-existing-image-descriptions +class CONTENT_EXPORT AXImageStopwords { + public: + static AXImageStopwords& GetInstance(); + + // The input should be a word, after already splitting by punctuation and + // whitespace. Returns true if the word is an image stopword. + // Case-insensitive and language-neutral (includes words from all + // languages). + bool IsImageStopword(const char* utf8_string) const; + + private: + friend base::NoDestructor<AXImageStopwords>; + + AXImageStopwords(); + ~AXImageStopwords(); + + base::flat_set<base::StringPiece> stopword_set_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_ACCESSIBILITY_AX_IMAGE_ANNOTATOR_H_ diff --git a/chromium/content/renderer/accessibility/ax_image_stopwords_unittest.cc b/chromium/content/renderer/accessibility/ax_image_stopwords_unittest.cc new file mode 100644 index 00000000000..21d6d938df8 --- /dev/null +++ b/chromium/content/renderer/accessibility/ax_image_stopwords_unittest.cc @@ -0,0 +1,116 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/accessibility/ax_image_stopwords.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +TEST(AXImageStopwordsTest, EmptyStringIsAStopword) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("")); +} + +TEST(AXImageStopwordsTest, English) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("the")); + EXPECT_TRUE(stopwords.IsImageStopword("http")); + EXPECT_TRUE(stopwords.IsImageStopword("for")); + EXPECT_TRUE(stopwords.IsImageStopword("with")); + EXPECT_TRUE(stopwords.IsImageStopword("background")); + EXPECT_TRUE(stopwords.IsImageStopword("sunday")); + EXPECT_TRUE(stopwords.IsImageStopword("november")); + EXPECT_FALSE(stopwords.IsImageStopword("cat")); + EXPECT_FALSE(stopwords.IsImageStopword("obama")); + EXPECT_FALSE(stopwords.IsImageStopword("heart")); + EXPECT_FALSE(stopwords.IsImageStopword("home")); +} + +TEST(AXImageStopwordsTest, EnglishCaseInsensitive) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("the")); + EXPECT_TRUE(stopwords.IsImageStopword("THE")); + EXPECT_TRUE(stopwords.IsImageStopword("tHe")); +} + +TEST(AXImageStopwordsTest, EnglishAllShortWordsAreStopwords) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + // One and two-letter words are always stopwords no matter what + // characters, as long as they're Latin characters. + EXPECT_TRUE(stopwords.IsImageStopword("q")); + EXPECT_TRUE(stopwords.IsImageStopword("I")); + EXPECT_TRUE(stopwords.IsImageStopword("ff")); + EXPECT_TRUE(stopwords.IsImageStopword("zU")); + + // Three-letter words aren't stopwords unless they're in our set. + EXPECT_FALSE(stopwords.IsImageStopword("fff")); + EXPECT_FALSE(stopwords.IsImageStopword("GGG")); +} + +TEST(AXImageStopwordsTest, French) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("les")); + EXPECT_TRUE(stopwords.IsImageStopword("BLANC")); + EXPECT_TRUE(stopwords.IsImageStopword("FÉVR")); + EXPECT_FALSE(stopwords.IsImageStopword("modèle")); + EXPECT_FALSE(stopwords.IsImageStopword("recettes")); + EXPECT_FALSE(stopwords.IsImageStopword("ciel")); +} + +TEST(AXImageStopwordsTest, Italian) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("con")); + EXPECT_TRUE(stopwords.IsImageStopword("PIÙ")); + EXPECT_TRUE(stopwords.IsImageStopword("Immagini")); + EXPECT_FALSE(stopwords.IsImageStopword("montagna")); + EXPECT_FALSE(stopwords.IsImageStopword("pubblico")); + EXPECT_FALSE(stopwords.IsImageStopword("Cultura")); +} + +TEST(AXImageStopwordsTest, German) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("und")); + EXPECT_TRUE(stopwords.IsImageStopword("FÜR")); + EXPECT_TRUE(stopwords.IsImageStopword("sprüche")); + EXPECT_FALSE(stopwords.IsImageStopword("haus")); + EXPECT_FALSE(stopwords.IsImageStopword("gesichter")); + EXPECT_FALSE(stopwords.IsImageStopword("Deutsche")); +} + +TEST(AXImageStopwordsTest, Spanish) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("con")); + EXPECT_TRUE(stopwords.IsImageStopword("MÁS")); + EXPECT_TRUE(stopwords.IsImageStopword("enero")); + EXPECT_FALSE(stopwords.IsImageStopword("tortuga")); + EXPECT_FALSE(stopwords.IsImageStopword("flores")); + EXPECT_FALSE(stopwords.IsImageStopword("actividades")); +} + +TEST(AXImageStopwordsTest, Hindi) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + EXPECT_TRUE(stopwords.IsImageStopword("रहे")); + EXPECT_TRUE(stopwords.IsImageStopword("चित्र")); + EXPECT_TRUE(stopwords.IsImageStopword("वीडियो")); + EXPECT_FALSE(stopwords.IsImageStopword("जानिए")); + EXPECT_FALSE(stopwords.IsImageStopword("भारतीय")); +} + +TEST(AXImageStopwordsTest, HindiShortWordsAreStopwords) { + AXImageStopwords& stopwords = AXImageStopwords::GetInstance(); + // All Hindi words with two or fewer unicode codepoints are stopwords. + // Note that these appear to have just one glyph, but they're encoded + // as two codepoints, a consonant and a vowel. + EXPECT_TRUE(stopwords.IsImageStopword("की")); // "of" + EXPECT_TRUE(stopwords.IsImageStopword("में")); // "in" + + // Some two-character Hindi words are stopwords, they're in our set. + EXPECT_TRUE(stopwords.IsImageStopword("एक")); // "one" + + // Other two-character Hindi words are not stopwords. + EXPECT_FALSE(stopwords.IsImageStopword("सदा")); // "always" + EXPECT_FALSE(stopwords.IsImageStopword("खाना")); // "food" +} + +} // namespace content diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc index 370c3edcba2..030d6487db7 100644 --- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc @@ -39,6 +39,7 @@ #include "third_party/blink/public/web/web_plugin.h" #include "third_party/blink/public/web/web_plugin_container.h" #include "third_party/blink/public/web/web_view.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/accessibility_switches.h" #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_role_properties.h" @@ -228,19 +229,20 @@ bool SearchForExactlyOneInnerImage(WebAXObject obj, if (!inner_image->IsDetached()) return false; *inner_image = obj; + } else { + // If we found something else with a name, fail. + if (!ui::IsDocument(obj.Role()) && !ui::IsLink(obj.Role())) { + blink::WebString web_name = obj.GetName(); + if (!base::ContainsOnlyChars(web_name.Utf8(), base::kWhitespaceASCII)) { + return false; + } + } } // Fail if we recursed to |max_depth| and there's more of a subtree. if (max_depth == 0 && obj.ChildCount()) return false; - // If we found something else with a name, fail. - if (obj.Role() != ax::mojom::Role::kRootWebArea) { - blink::WebString web_name = obj.GetName(); - if (!base::ContainsOnlyChars(web_name.Utf8(), base::kWhitespaceASCII)) - return false; - } - // Recurse. for (unsigned int i = 0; i < obj.ChildCount(); i++) { if (!SearchForExactlyOneInnerImage(obj.ChildAt(i), inner_image, @@ -251,12 +253,12 @@ bool SearchForExactlyOneInnerImage(WebAXObject obj, return !inner_image->IsDetached(); } -// Return true if the subtree of |obj|, to a max depth of 2, contains +// Return true if the subtree of |obj|, to a max depth of 3, contains // exactly one image. Return that image in |inner_image|. -bool FindExactlyOneInnerImageInMaxDepthTwo(WebAXObject obj, - WebAXObject* inner_image) { +bool FindExactlyOneInnerImageInMaxDepthThree(WebAXObject obj, + WebAXObject* inner_image) { DCHECK(inner_image); - return SearchForExactlyOneInnerImage(obj, inner_image, /* max_depth = */ 2); + return SearchForExactlyOneInnerImage(obj, inner_image, /* max_depth = */ 3); } std::string GetEquivalentAriaRoleString(const ax::mojom::Role role) { @@ -410,10 +412,6 @@ void BlinkAXTreeSource::SetLoadInlineTextBoxesForId(int32_t id) { load_inline_text_boxes_ids_.insert(id); } -void BlinkAXTreeSource::EnableDOMNodeIDs() { - enable_dom_node_ids_ = true; -} - bool BlinkAXTreeSource::GetTreeData(AXContentTreeData* tree_data) const { CHECK(frozen_); tree_data->doctype = "html"; @@ -574,6 +572,94 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, TRACE_EVENT1("accessibility", "BlinkAXTreeSource::SerializeNode", "role", ui::ToString(dst->role)); + SerializeNameAndDescriptionAttributes(src, dst); + + if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader) || + accessibility_mode_.has_mode(ui::AXMode::kPDF)) { + // Heading level. + if (ui::IsHeading(dst->role) && src.HeadingLevel()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel, + src.HeadingLevel()); + } + + SerializeListAttributes(src, dst); + SerializeTableAttributes(src, dst); + } + + if (accessibility_mode_.has_mode(ui::AXMode::kPDF)) { + SerializePDFAttributes(src, dst); + // Return early. None of the following attributes are needed for PDFs. + return; + } + + SerializeBoundingBoxAttributes(src, dst); + + SerializeSparseAttributes(src, dst); + SerializeValueAttributes(src, dst); + SerializeStateAttributes(src, dst); + SerializeChooserPopupAttributes(src, dst); + + if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader)) { + SerializeStyleAttributes(src, dst); + SerializeMarkerAttributes(src, dst); + if (src.IsInLiveRegion()) + SerializeLiveRegionAttributes(src, dst); + SerializeOtherScreenReaderAttributes(src, dst); + } + + WebNode node = src.GetNode(); + bool is_iframe = false; + if (!node.IsNull() && node.IsElementNode()) { + WebElement element = node.To<WebElement>(); + is_iframe = element.HasHTMLTagName("iframe"); + + SerializeElementAttributes(src, element, dst); + if (accessibility_mode_.has_mode(ui::AXMode::kHTML)) { + SerializeHTMLAttributes(src, element, dst); + } + + if (src.IsEditable()) { + SerializeEditableTextAttributes(src, dst); + } + + // Presence of other ARIA attributes. + if (src.HasAriaAttribute()) + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kHasAriaAttribute, true); + } + + // Add the ids of *indirect* children - those who are children of this node, + // but whose parent is *not* this node. One example is a table + // cell, which is a child of both a row and a column. Because the cell's + // parent is the row, the row adds it as a child, and the column adds it + // as an indirect child. + int child_count = src.ChildCount(); + std::vector<int32_t> indirect_child_ids; + for (int i = 0; i < child_count; ++i) { + WebAXObject child = src.ChildAt(i); + if (!is_iframe && !child.IsDetached() && !IsParentUnignoredOf(src, child)) + indirect_child_ids.push_back(child.AxID()); + } + if (indirect_child_ids.size() > 0) { + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kIndirectChildIds, + indirect_child_ids); + } + + if (src.IsScrollableContainer()) { + SerializeScrollAttributes(src, dst); + } + + if (dst->id == image_data_node_id_) { + // In general, string attributes should be truncated using + // TruncateAndAddStringAttribute, but ImageDataUrl contains a data url + // representing an image, so add it directly using AddStringAttribute. + dst->AddStringAttribute(ax::mojom::StringAttribute::kImageDataUrl, + src.ImageDataUrl(max_image_data_size_).Utf8()); + } +} + +void BlinkAXTreeSource::SerializeBoundingBoxAttributes( + WebAXObject src, + AXContentNodeData* dst) const { WebAXObject offset_container; WebFloatRect bounds_in_container; SkMatrix44 container_transform; @@ -604,30 +690,29 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, dst->AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true); } +} - if (enable_dom_node_ids_) { - // The DOMNodeID from Blink. Currently only populated when using - // the accessibility tree for PDF exporting. Warning, this is totally - // unrelated to the accessibility node ID, or the ID attribute for an - // HTML element - it's an ID used to uniquely identify nodes in Blink. - int dom_node_id = src.GetDOMNodeId(); - if (dom_node_id) - dst->AddIntAttribute(ax::mojom::IntAttribute::kDOMNodeId, dom_node_id); - } +void BlinkAXTreeSource::SerializePDFAttributes(WebAXObject src, + AXContentNodeData* dst) const { + // The DOMNodeID from Blink. Currently only populated when using + // the accessibility tree for PDF exporting. Warning, this is totally + // unrelated to the accessibility node ID, or the ID attribute for an + // HTML element - it's an ID used to uniquely identify nodes in Blink. + int dom_node_id = src.GetDOMNodeId(); + if (dom_node_id) + dst->AddIntAttribute(ax::mojom::IntAttribute::kDOMNodeId, dom_node_id); +} +void BlinkAXTreeSource::SerializeSparseAttributes( + WebAXObject src, + AXContentNodeData* dst) const { AXContentNodeDataSparseAttributeAdapter sparse_attribute_adapter(dst); src.GetSparseAXAttributes(sparse_attribute_adapter); +} - WebAXObject chooser_popup = src.ChooserPopup(); - if (!chooser_popup.IsNull()) { - int32_t chooser_popup_id = chooser_popup.AxID(); - auto controls_ids = - dst->GetIntListAttribute(ax::mojom::IntListAttribute::kControlsIds); - controls_ids.push_back(chooser_popup_id); - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds, - controls_ids); - } - +void BlinkAXTreeSource::SerializeNameAndDescriptionAttributes( + WebAXObject src, + AXContentNodeData* dst) const { ax::mojom::NameFrom name_from; blink::WebVector<WebAXObject> name_objects; blink::WebString web_name = src.GetName(name_from, name_objects); @@ -661,6 +746,17 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, web_title.Utf8()); } + if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader)) { + blink::WebString web_placeholder = src.Placeholder(name_from); + if (!web_placeholder.IsEmpty()) + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kPlaceholder, + web_placeholder.Utf8()); + } +} + +void BlinkAXTreeSource::SerializeValueAttributes(WebAXObject src, + AXContentNodeData* dst) const { if (src.ValueDescription().length()) { TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue, src.ValueDescription().Utf8()); @@ -668,7 +764,10 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue, src.StringValue().Utf8()); } +} +void BlinkAXTreeSource::SerializeStateAttributes(WebAXObject src, + AXContentNodeData* dst) const { switch (src.Restriction()) { case blink::kWebAXRestrictionReadOnly: dst->SetRestriction(ax::mojom::Restriction::kReadOnly); @@ -685,529 +784,517 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, if (!src.Url().IsEmpty()) TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kUrl, src.Url().GetString().Utf8()); +} - // The following set of attributes are only accessed when the accessibility - // mode is set to screen reader mode, otherwise only the more basic - // attributes are populated. - if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader)) { - blink::WebString web_placeholder = src.Placeholder(name_from); - if (!web_placeholder.IsEmpty()) - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kPlaceholder, - web_placeholder.Utf8()); +void BlinkAXTreeSource::SerializeStyleAttributes(WebAXObject src, + AXContentNodeData* dst) const { + // Text attributes. + if (src.BackgroundColor()) + dst->AddIntAttribute(ax::mojom::IntAttribute::kBackgroundColor, + src.BackgroundColor()); - if (dst->role == ax::mojom::Role::kColorWell) - dst->AddIntAttribute(ax::mojom::IntAttribute::kColorValue, - src.ColorValue()); + if (src.GetColor()) + dst->AddIntAttribute(ax::mojom::IntAttribute::kColor, src.GetColor()); - if (dst->role == ax::mojom::Role::kLink) { - WebAXObject target = src.InPageLinkTarget(); - if (!target.IsNull()) { - int32_t target_id = target.AxID(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kInPageLinkTargetId, - target_id); - } - } + WebAXObject parent = ParentObjectUnignored(src); + if (src.FontFamily().length()) { + if (parent.IsNull() || parent.FontFamily() != src.FontFamily()) + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kFontFamily, + src.FontFamily().Utf8()); + } - if (dst->role == ax::mojom::Role::kRadioButton) { - AddIntListAttributeFromWebObjects( - ax::mojom::IntListAttribute::kRadioGroupIds, - src.RadioButtonsInGroup(), dst); - } + // Font size is in pixels. + if (src.FontSize()) + dst->AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize, + src.FontSize()); - // Text attributes. - if (src.BackgroundColor()) - dst->AddIntAttribute(ax::mojom::IntAttribute::kBackgroundColor, - src.BackgroundColor()); + if (src.FontWeight()) { + dst->AddFloatAttribute(ax::mojom::FloatAttribute::kFontWeight, + src.FontWeight()); + } - if (src.GetColor()) - dst->AddIntAttribute(ax::mojom::IntAttribute::kColor, src.GetColor()); + if (dst->role == ax::mojom::Role::kListItem && + src.GetListStyle() != ax::mojom::ListStyle::kNone) { + dst->SetListStyle(src.GetListStyle()); + } - WebAXObject parent = ParentObjectUnignored(src); - if (src.FontFamily().length()) { - if (parent.IsNull() || parent.FontFamily() != src.FontFamily()) - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kFontFamily, - src.FontFamily().Utf8()); - } + if (src.GetTextDirection() != ax::mojom::TextDirection::kNone) { + dst->SetTextDirection(src.GetTextDirection()); + } - // Font size is in pixels. - if (src.FontSize()) - dst->AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize, - src.FontSize()); + if (src.GetTextPosition() != ax::mojom::TextPosition::kNone) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextPosition, + static_cast<int32_t>(src.GetTextPosition())); + } - if (src.FontWeight()) { - dst->AddFloatAttribute(ax::mojom::FloatAttribute::kFontWeight, - src.FontWeight()); - } + int32_t text_style = 0; + ax::mojom::TextDecorationStyle text_overline_style; + ax::mojom::TextDecorationStyle text_strikethrough_style; + ax::mojom::TextDecorationStyle text_underline_style; + src.GetTextStyleAndTextDecorationStyle(&text_style, &text_overline_style, + &text_strikethrough_style, + &text_underline_style); + if (text_style) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextStyle, text_style); + } - if (src.AriaCurrentState() != ax::mojom::AriaCurrentState::kNone) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState, - static_cast<int32_t>(src.AriaCurrentState())); - } + if (text_overline_style != ax::mojom::TextDecorationStyle::kNone) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextOverlineStyle, + static_cast<int32_t>(text_overline_style)); + } - if (src.InvalidState() != ax::mojom::InvalidState::kNone) - dst->SetInvalidState(src.InvalidState()); - if (src.InvalidState() == ax::mojom::InvalidState::kOther && - src.AriaInvalidValue().length()) { - TruncateAndAddStringAttribute( - dst, ax::mojom::StringAttribute::kAriaInvalidValue, - src.AriaInvalidValue().Utf8()); - } + if (text_strikethrough_style != ax::mojom::TextDecorationStyle::kNone) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextStrikethroughStyle, + static_cast<int32_t>(text_strikethrough_style)); + } - if (src.CheckedState() != ax::mojom::CheckedState::kNone) { - dst->SetCheckedState(src.CheckedState()); - } + if (text_underline_style != ax::mojom::TextDecorationStyle::kNone) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextUnderlineStyle, + static_cast<int32_t>(text_underline_style)); + } +} - if (dst->role == ax::mojom::Role::kListItem && - src.GetListStyle() != ax::mojom::ListStyle::kNone) { - dst->SetListStyle(src.GetListStyle()); - } +void BlinkAXTreeSource::SerializeInlineTextBoxAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + DCHECK_EQ(ax::mojom::Role::kInlineTextBox, dst->role); + + WebVector<int> src_character_offsets; + src.CharacterOffsets(src_character_offsets); + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kCharacterOffsets, + src_character_offsets.ReleaseVector()); + + WebVector<int> src_word_starts; + WebVector<int> src_word_ends; + src.GetWordBoundaries(src_word_starts, src_word_ends); + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts, + src_word_starts.ReleaseVector()); + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, + src_word_ends.ReleaseVector()); +} - if (src.GetTextDirection() != ax::mojom::TextDirection::kNone) { - dst->SetTextDirection(src.GetTextDirection()); +void BlinkAXTreeSource::SerializeMarkerAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + // Spelling, grammar and other document markers. + WebVector<ax::mojom::MarkerType> src_marker_types; + WebVector<int> src_marker_starts; + WebVector<int> src_marker_ends; + src.Markers(src_marker_types, src_marker_starts, src_marker_ends); + DCHECK_EQ(src_marker_types.size(), src_marker_starts.size()); + DCHECK_EQ(src_marker_starts.size(), src_marker_ends.size()); + + if (src_marker_types.size()) { + std::vector<int32_t> marker_types; + std::vector<int32_t> marker_starts; + std::vector<int32_t> marker_ends; + marker_types.reserve(src_marker_types.size()); + marker_starts.reserve(src_marker_starts.size()); + marker_ends.reserve(src_marker_ends.size()); + for (size_t i = 0; i < src_marker_types.size(); ++i) { + marker_types.push_back(static_cast<int32_t>(src_marker_types[i])); + marker_starts.push_back(src_marker_starts[i]); + marker_ends.push_back(src_marker_ends[i]); } + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerTypes, + marker_types); + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerStarts, + marker_starts); + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerEnds, + marker_ends); + } +} - if (src.GetTextPosition() != ax::mojom::TextPosition::kNone) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextPosition, - static_cast<int32_t>(src.GetTextPosition())); - } +void BlinkAXTreeSource::SerializeLiveRegionAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + DCHECK(src.IsInLiveRegion()); - int32_t text_style = 0; - ax::mojom::TextDecorationStyle text_overline_style; - ax::mojom::TextDecorationStyle text_strikethrough_style; - ax::mojom::TextDecorationStyle text_underline_style; - src.GetTextStyleAndTextDecorationStyle(&text_style, &text_overline_style, - &text_strikethrough_style, - &text_underline_style); - if (text_style) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextStyle, text_style); - } + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, + src.LiveRegionAtomic()); + if (!src.LiveRegionStatus().IsEmpty()) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kLiveStatus, + src.LiveRegionStatus().Utf8()); + } + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kLiveRelevant, + src.LiveRegionRelevant().Utf8()); + // If we are not at the root of an atomic live region. + if (src.ContainerLiveRegionAtomic() && !src.LiveRegionRoot().IsDetached() && + !src.LiveRegionAtomic()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kMemberOfId, + src.LiveRegionRoot().AxID()); + } + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveAtomic, + src.ContainerLiveRegionAtomic()); + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveBusy, + src.ContainerLiveRegionBusy()); + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kContainerLiveStatus, + src.ContainerLiveRegionStatus().Utf8()); + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kContainerLiveRelevant, + src.ContainerLiveRegionRelevant().Utf8()); +} - if (text_overline_style != ax::mojom::TextDecorationStyle::kNone) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextOverlineStyle, - static_cast<int32_t>(text_overline_style)); - } +void BlinkAXTreeSource::SerializeListAttributes(WebAXObject src, + AXContentNodeData* dst) const { + if (src.SetSize()) + dst->AddIntAttribute(ax::mojom::IntAttribute::kSetSize, src.SetSize()); - if (text_strikethrough_style != ax::mojom::TextDecorationStyle::kNone) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextStrikethroughStyle, - static_cast<int32_t>(text_strikethrough_style)); - } + if (src.PosInSet()) + dst->AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, src.PosInSet()); +} - if (text_underline_style != ax::mojom::TextDecorationStyle::kNone) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextUnderlineStyle, - static_cast<int32_t>(text_underline_style)); +void BlinkAXTreeSource::SerializeTableAttributes(WebAXObject src, + AXContentNodeData* dst) const { + const bool is_table_like_role = ui::IsTableLike(dst->role); + if (is_table_like_role) { + int aria_colcount = src.AriaColumnCount(); + if (aria_colcount) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount, + aria_colcount); } - if (dst->role == ax::mojom::Role::kInlineTextBox) { - WebVector<int> src_character_offsets; - src.CharacterOffsets(src_character_offsets); - std::vector<int32_t> character_offsets; - character_offsets.reserve(src_character_offsets.size()); - for (size_t i = 0; i < src_character_offsets.size(); ++i) - character_offsets.push_back(src_character_offsets[i]); - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kCharacterOffsets, - character_offsets); - - WebVector<int> src_word_starts; - WebVector<int> src_word_ends; - src.GetWordBoundaries(src_word_starts, src_word_ends); - std::vector<int32_t> word_starts; - std::vector<int32_t> word_ends; - word_starts.reserve(src_word_starts.size()); - word_ends.reserve(src_word_starts.size()); - for (size_t i = 0; i < src_word_starts.size(); ++i) { - word_starts.push_back(src_word_starts[i]); - word_ends.push_back(src_word_ends[i]); - } - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts, - word_starts); - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, - word_ends); + int aria_rowcount = src.AriaRowCount(); + if (aria_rowcount) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount, + aria_rowcount); } + } - if (src.AccessKey().length()) { - TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kAccessKey, - src.AccessKey().Utf8()); + if (ui::IsTableRow(dst->role)) { + WebAXObject header = src.RowHeader(); + if (!header.IsDetached()) { + // TODO(accessibility): these should be computed by ui::AXTableInfo and + // removed here. + dst->AddIntAttribute(ax::mojom::IntAttribute::kTableRowHeaderId, + header.AxID()); } + } - if (src.AutoComplete().length()) { - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kAutoComplete, - src.AutoComplete().Utf8()); - } + if (ui::IsCellOrTableHeader(dst->role)) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan, + src.CellColumnSpan()); + dst->AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan, + src.CellRowSpan()); + } - if (src.Action() != ax::mojom::DefaultActionVerb::kNone) { - dst->SetDefaultActionVerb(src.Action()); + if (ui::IsCellOrTableHeader(dst->role) || ui::IsTableRow(dst->role)) { + // aria-rowindex and aria-colindex are supported on cells, headers and + // rows. + int aria_rowindex = src.AriaRowIndex(); + if (aria_rowindex) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex, + aria_rowindex); } - blink::WebString display_style = src.ComputedStyleDisplay(); - if (!display_style.IsEmpty()) { - TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDisplay, - display_style.Utf8()); + int aria_colindex = src.AriaColumnIndex(); + if (aria_colindex) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCellColumnIndex, + aria_colindex); } + } - if (src.Language().length()) { - if (parent.IsNull() || parent.Language() != src.Language()) - TruncateAndAddStringAttribute( - dst, ax::mojom::StringAttribute::kLanguage, src.Language().Utf8()); - } + if (ui::IsTableHeader(dst->role) && + src.SortDirection() != ax::mojom::SortDirection::kNone) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kSortDirection, + static_cast<int32_t>(src.SortDirection())); + } +} - if (src.KeyboardShortcut().length() && - !dst->HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) { - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kKeyShortcuts, - src.KeyboardShortcut().Utf8()); - } +void BlinkAXTreeSource::SerializeScrollAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + // Only mark as scrollable if user has actual scrollbars to use. + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, + src.IsUserScrollable()); + // Provide x,y scroll info if scrollable in any way (programmatically or via + // user). + const gfx::Point& scroll_offset = src.GetScrollOffset(); + dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, scroll_offset.x()); + dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, scroll_offset.y()); + + const gfx::Point& min_scroll_offset = src.MinimumScrollOffset(); + dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, + min_scroll_offset.x()); + dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin, + min_scroll_offset.y()); + + const gfx::Point& max_scroll_offset = src.MaximumScrollOffset(); + dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax, + max_scroll_offset.x()); + dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax, + max_scroll_offset.y()); +} - if (!src.NextOnLine().IsDetached()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId, - src.NextOnLine().AxID()); - } +void BlinkAXTreeSource::SerializeChooserPopupAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + WebAXObject chooser_popup = src.ChooserPopup(); + if (!chooser_popup.IsNull()) { + int32_t chooser_popup_id = chooser_popup.AxID(); + auto controls_ids = + dst->GetIntListAttribute(ax::mojom::IntListAttribute::kControlsIds); + controls_ids.push_back(chooser_popup_id); + dst->AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds, + controls_ids); + } +} - if (!src.PreviousOnLine().IsDetached()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId, - src.PreviousOnLine().AxID()); +void BlinkAXTreeSource::SerializeOtherScreenReaderAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + if (dst->role == ax::mojom::Role::kColorWell) + dst->AddIntAttribute(ax::mojom::IntAttribute::kColorValue, + src.ColorValue()); + + if (dst->role == ax::mojom::Role::kLink) { + WebAXObject target = src.InPageLinkTarget(); + if (!target.IsNull()) { + int32_t target_id = target.AxID(); + dst->AddIntAttribute(ax::mojom::IntAttribute::kInPageLinkTargetId, + target_id); } + } - if (!src.AriaActiveDescendant().IsDetached()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kActivedescendantId, - src.AriaActiveDescendant().AxID()); - } + if (dst->role == ax::mojom::Role::kRadioButton) { + AddIntListAttributeFromWebObjects( + ax::mojom::IntListAttribute::kRadioGroupIds, src.RadioButtonsInGroup(), + dst); + } - if (!src.ErrorMessage().IsDetached()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kErrormessageId, - src.ErrorMessage().AxID()); - } + if (src.AriaCurrentState() != ax::mojom::AriaCurrentState::kNone) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState, + static_cast<int32_t>(src.AriaCurrentState())); + } - if (ui::IsHeading(dst->role) && src.HeadingLevel()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel, - src.HeadingLevel()); - } else if (ui::SupportsHierarchicalLevel(dst->role) && - src.HierarchicalLevel()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel, - src.HierarchicalLevel()); - } + if (src.InvalidState() != ax::mojom::InvalidState::kNone) + dst->SetInvalidState(src.InvalidState()); + if (src.InvalidState() == ax::mojom::InvalidState::kOther && + src.AriaInvalidValue().length()) { + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kAriaInvalidValue, + src.AriaInvalidValue().Utf8()); + } - if (src.SetSize()) - dst->AddIntAttribute(ax::mojom::IntAttribute::kSetSize, src.SetSize()); - - if (src.PosInSet()) - dst->AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, src.PosInSet()); - - if (src.CanvasHasFallbackContent()) - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kCanvasHasFallback, true); - - // Spelling, grammar and other document markers. - WebVector<ax::mojom::MarkerType> src_marker_types; - WebVector<int> src_marker_starts; - WebVector<int> src_marker_ends; - src.Markers(src_marker_types, src_marker_starts, src_marker_ends); - DCHECK_EQ(src_marker_types.size(), src_marker_starts.size()); - DCHECK_EQ(src_marker_starts.size(), src_marker_ends.size()); - - if (src_marker_types.size()) { - std::vector<int32_t> marker_types; - std::vector<int32_t> marker_starts; - std::vector<int32_t> marker_ends; - marker_types.reserve(src_marker_types.size()); - marker_starts.reserve(src_marker_starts.size()); - marker_ends.reserve(src_marker_ends.size()); - for (size_t i = 0; i < src_marker_types.size(); ++i) { - marker_types.push_back(static_cast<int32_t>(src_marker_types[i])); - marker_starts.push_back(src_marker_starts[i]); - marker_ends.push_back(src_marker_ends[i]); - } - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerTypes, - marker_types); - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerStarts, - marker_starts); - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerEnds, - marker_ends); - } + if (src.CheckedState() != ax::mojom::CheckedState::kNone) { + dst->SetCheckedState(src.CheckedState()); + } - if (src.IsInLiveRegion()) { - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, - src.LiveRegionAtomic()); - if (!src.LiveRegionStatus().IsEmpty()) { - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kLiveStatus, - src.LiveRegionStatus().Utf8()); - } - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kLiveRelevant, - src.LiveRegionRelevant().Utf8()); - // If we are not at the root of an atomic live region. - if (src.ContainerLiveRegionAtomic() && - !src.LiveRegionRoot().IsDetached() && !src.LiveRegionAtomic()) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kMemberOfId, - src.LiveRegionRoot().AxID()); - } - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveAtomic, - src.ContainerLiveRegionAtomic()); - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveBusy, - src.ContainerLiveRegionBusy()); - TruncateAndAddStringAttribute( - dst, ax::mojom::StringAttribute::kContainerLiveStatus, - src.ContainerLiveRegionStatus().Utf8()); - TruncateAndAddStringAttribute( - dst, ax::mojom::StringAttribute::kContainerLiveRelevant, - src.ContainerLiveRegionRelevant().Utf8()); - } + if (dst->role == ax::mojom::Role::kInlineTextBox) { + SerializeInlineTextBoxAttributes(src, dst); + } - if (dst->role == ax::mojom::Role::kProgressIndicator || - dst->role == ax::mojom::Role::kMeter || - dst->role == ax::mojom::Role::kScrollBar || - dst->role == ax::mojom::Role::kSlider || - dst->role == ax::mojom::Role::kSpinButton || - (dst->role == ax::mojom::Role::kSplitter && - dst->HasState(ax::mojom::State::kFocusable))) { - float value; - if (src.ValueForRange(&value)) - dst->AddFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, - value); - - float max_value; - if (src.MaxValueForRange(&max_value)) { - dst->AddFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange, - max_value); - } + if (src.AccessKey().length()) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kAccessKey, + src.AccessKey().Utf8()); + } - float min_value; - if (src.MinValueForRange(&min_value)) { - dst->AddFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange, - min_value); - } + if (src.AutoComplete().length()) { + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kAutoComplete, + src.AutoComplete().Utf8()); + } - float step_value; - if (src.StepValueForRange(&step_value)) { - dst->AddFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, - step_value); - } - } + if (src.Action() != ax::mojom::DefaultActionVerb::kNone) { + dst->SetDefaultActionVerb(src.Action()); + } - if (ui::IsDialog(dst->role)) { - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kModal, src.IsModal()); - } + blink::WebString display_style = src.ComputedStyleDisplay(); + if (!display_style.IsEmpty()) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDisplay, + display_style.Utf8()); + } - if (dst->role == ax::mojom::Role::kRootWebArea) - TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kHtmlTag, - "#document"); + WebAXObject parent = ParentObjectUnignored(src); + if (src.Language().length()) { + if (parent.IsNull() || parent.Language() != src.Language()) + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kLanguage, + src.Language().Utf8()); + } - const bool is_table_like_role = ui::IsTableLike(dst->role); - if (is_table_like_role) { - int aria_colcount = src.AriaColumnCount(); - if (aria_colcount) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount, - aria_colcount); - } + if (src.KeyboardShortcut().length() && + !dst->HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) { + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kKeyShortcuts, + src.KeyboardShortcut().Utf8()); + } - int aria_rowcount = src.AriaRowCount(); - if (aria_rowcount) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount, - aria_rowcount); - } - } + if (!src.NextOnLine().IsDetached()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId, + src.NextOnLine().AxID()); + } - if (ui::IsTableRow(dst->role)) { - WebAXObject header = src.RowHeader(); - if (!header.IsDetached()) { - // TODO(accessibility): these should be computed by ui::AXTableInfo and - // removed here. - dst->AddIntAttribute(ax::mojom::IntAttribute::kTableRowHeaderId, - header.AxID()); - } - } + if (!src.PreviousOnLine().IsDetached()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId, + src.PreviousOnLine().AxID()); + } - if (ui::IsCellOrTableHeader(dst->role)) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan, - src.CellColumnSpan()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan, - src.CellRowSpan()); - } + if (!src.AriaActiveDescendant().IsDetached()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kActivedescendantId, + src.AriaActiveDescendant().AxID()); + } - if (ui::IsCellOrTableHeader(dst->role) || ui::IsTableRow(dst->role)) { - // aria-rowindex and aria-colindex are supported on cells, headers and - // rows. - int aria_rowindex = src.AriaRowIndex(); - if (aria_rowindex) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex, - aria_rowindex); - } + if (!src.ErrorMessage().IsDetached()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kErrormessageId, + src.ErrorMessage().AxID()); + } - int aria_colindex = src.AriaColumnIndex(); - if (aria_colindex) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCellColumnIndex, - aria_colindex); - } - } + if (ui::SupportsHierarchicalLevel(dst->role) && src.HierarchicalLevel()) { + dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel, + src.HierarchicalLevel()); + } - if (ui::IsTableHeader(dst->role) && - src.SortDirection() != ax::mojom::SortDirection::kNone) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kSortDirection, - static_cast<int32_t>(src.SortDirection())); + if (src.CanvasHasFallbackContent()) + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kCanvasHasFallback, true); + + if (dst->role == ax::mojom::Role::kProgressIndicator || + dst->role == ax::mojom::Role::kMeter || + dst->role == ax::mojom::Role::kScrollBar || + dst->role == ax::mojom::Role::kSlider || + dst->role == ax::mojom::Role::kSpinButton || + (dst->role == ax::mojom::Role::kSplitter && + dst->HasState(ax::mojom::State::kFocusable))) { + float value; + if (src.ValueForRange(&value)) + dst->AddFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, value); + + float max_value; + if (src.MaxValueForRange(&max_value)) { + dst->AddFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange, + max_value); } - if (dst->role == ax::mojom::Role::kImage) - AddImageAnnotations(src, dst); - - // If a link or web area isn't otherwise labeled and contains - // exactly one image (searching only to a max depth of 2), - // annotate the link/web area with the image's annotation, too. - if (dst->role == ax::mojom::Role::kLink || - dst->role == ax::mojom::Role::kRootWebArea) { - WebAXObject inner_image; - if (FindExactlyOneInnerImageInMaxDepthTwo(src, &inner_image)) - AddImageAnnotations(inner_image, dst); + float min_value; + if (src.MinValueForRange(&min_value)) { + dst->AddFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange, + min_value); } - WebNode node = src.GetNode(); - if (!node.IsNull() && node.IsElementNode()) { - WebElement element = node.To<WebElement>(); - if (element.HasHTMLTagName("input") && element.HasAttribute("type")) { - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kInputType, - element.GetAttribute("type").Utf8()); - } + float step_value; + if (src.StepValueForRange(&step_value)) { + dst->AddFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, + step_value); } } - // The majority of the rest of this code computes attributes needed for - // all modes, not just for screen readers. + if (ui::IsDialog(dst->role)) { + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kModal, src.IsModal()); + } - WebNode node = src.GetNode(); - bool is_iframe = false; + if (dst->role == ax::mojom::Role::kRootWebArea) + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kHtmlTag, + "#document"); + + if (dst->role == ax::mojom::Role::kImage) + AddImageAnnotations(src, dst); + + // If a link or web area isn't otherwise labeled and contains exactly one + // image (searching only to a max depth of 2), and the link doesn't have + // accessible text from an attribute like aria-label, then annotate the + // link/web area with the image's annotation, too. + if ((ui::IsLink(dst->role) || ui::IsDocument(dst->role)) && + dst->GetNameFrom() != ax::mojom::NameFrom::kAttribute) { + WebAXObject inner_image; + if (FindExactlyOneInnerImageInMaxDepthThree(src, &inner_image)) + AddImageAnnotations(inner_image, dst); + } + WebNode node = src.GetNode(); if (!node.IsNull() && node.IsElementNode()) { WebElement element = node.To<WebElement>(); - is_iframe = element.HasHTMLTagName("iframe"); - - if (element.HasAttribute("class")) { - TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kClassName, - element.GetAttribute("class").Utf8()); - } - if (accessibility_mode_.has_mode(ui::AXMode::kHTML)) { - // TODO(ctguil): The tagName in WebKit is lower cased but - // HTMLElement::nodeName calls localNameUpper. Consider adding - // a WebElement method that returns the original lower cased tagName. - TruncateAndAddStringAttribute( - dst, ax::mojom::StringAttribute::kHtmlTag, - base::ToLowerASCII(element.TagName().Utf8())); - for (unsigned i = 0; i < element.AttributeCount(); ++i) { - std::string name = - base::ToLowerASCII(element.AttributeLocalName(i).Utf8()); - if (name != "class") { // class already in kClassName. - std::string value = element.AttributeValue(i).Utf8(); - dst->html_attributes.push_back(std::make_pair(name, value)); - } - } - -// TODO(nektar): Turn off kHTMLAccessibilityMode for automation and Mac -// and remove ifdef. -#if defined(OS_WIN) || defined(OS_CHROMEOS) - if (dst->role == ax::mojom::Role::kMath && element.InnerHTML().length()) { - TruncateAndAddStringAttribute(dst, - ax::mojom::StringAttribute::kInnerHtml, - element.InnerHTML().Utf8()); - } -#endif - } - - if (src.IsEditable()) { - if (src.IsEditableRoot()) - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true); - - if (src.IsControl() && - !dst->HasState(ax::mojom::State::kRichlyEditable)) { - // Only for simple input controls -- rich editable areas use AXTreeData. - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart, - src.SelectionStart()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, - src.SelectionEnd()); - } + if (element.HasHTMLTagName("input") && element.HasAttribute("type")) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kInputType, + element.GetAttribute("type").Utf8()); } + } - // ARIA role. - if (element.HasAttribute("role")) { - TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole, - element.GetAttribute("role").Utf8()); - } else { - std::string role = GetEquivalentAriaRoleString(dst->role); - if (!role.empty()) - TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole, - role); + // aria-dropeffect is deprecated in WAI-ARIA 1.1. + WebVector<ax::mojom::Dropeffect> src_dropeffects; + src.Dropeffects(src_dropeffects); + if (!src_dropeffects.empty()) { + for (auto&& dropeffect : src_dropeffects) { + dst->AddDropeffect(dropeffect); } - - // Presence of other ARIA attributes. - if (src.HasAriaAttribute()) - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kHasAriaAttribute, true); - - // Frames and iframes: - // If there are children, the fallback content has been rendered and should - // be used instead. For example, the fallback content may be rendered if - // there was an error loading an <object>. In that case, only expose the - // children. A node should not have both children and a child tree. - WebFrame* frame = WebFrame::FromFrameOwnerElement(element); - if (frame && !src.ChildCount()) - dst->child_routing_id = RenderFrame::GetRoutingIdForWebFrame(frame); } +} - // Add the ids of *indirect* children - those who are children of this node, - // but whose parent is *not* this node. One example is a table - // cell, which is a child of both a row and a column. Because the cell's - // parent is the row, the row adds it as a child, and the column adds it - // as an indirect child. - int child_count = src.ChildCount(); - std::vector<int32_t> indirect_child_ids; - for (int i = 0; i < child_count; ++i) { - WebAXObject child = src.ChildAt(i); - if (!is_iframe && !child.IsDetached() && !IsParentUnignoredOf(src, child)) - indirect_child_ids.push_back(child.AxID()); - } - if (indirect_child_ids.size() > 0) { - dst->AddIntListAttribute(ax::mojom::IntListAttribute::kIndirectChildIds, - indirect_child_ids); +void BlinkAXTreeSource::SerializeEditableTextAttributes( + WebAXObject src, + AXContentNodeData* dst) const { + DCHECK(src.IsEditable()); + + if (src.IsEditableRoot()) + dst->AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true); + + if (src.IsNativeTextControl()) { + // Selection offsets are only used for plain text controls, (input of a text + // field type, and textarea). Rich editable areas, such as contenteditables, + // use AXTreeData. + // + // TODO(nektar): Remove kTextSelStart and kTextSelEnd from the renderer. + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart, + src.SelectionStart()); + dst->AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, + src.SelectionEnd()); } +} - if (src.IsScrollableContainer()) { - // Only mark as scrollable if user has actual scrollbars to use. - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, - src.IsUserScrollable()); - // Provide x,y scroll info if scrollable in any way (programmatically or via - // user). - const gfx::Point& scroll_offset = src.GetScrollOffset(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, scroll_offset.x()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, scroll_offset.y()); - - const gfx::Point& min_scroll_offset = src.MinimumScrollOffset(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, - min_scroll_offset.x()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin, - min_scroll_offset.y()); - - const gfx::Point& max_scroll_offset = src.MaximumScrollOffset(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax, - max_scroll_offset.x()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax, - max_scroll_offset.y()); +void BlinkAXTreeSource::SerializeElementAttributes( + WebAXObject src, + WebElement element, + AXContentNodeData* dst) const { + if (element.HasAttribute("class")) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kClassName, + element.GetAttribute("class").Utf8()); } - if (dst->id == image_data_node_id_) { - // In general, string attributes should be truncated using - // TruncateAndAddStringAttribute, but ImageDataUrl contains a data url - // representing an image, so add it directly using AddStringAttribute. - dst->AddStringAttribute(ax::mojom::StringAttribute::kImageDataUrl, - src.ImageDataUrl(max_image_data_size_).Utf8()); + // ARIA role. + if (element.HasAttribute("role")) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole, + element.GetAttribute("role").Utf8()); + } else { + std::string role = GetEquivalentAriaRoleString(dst->role); + if (!role.empty()) + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole, + role); } - // aria-dropeffect is deprecated in WAI-ARIA 1.1. - WebVector<ax::mojom::Dropeffect> src_dropeffects; - src.Dropeffects(src_dropeffects); - if (!src_dropeffects.empty()) { - for (auto&& dropeffect : src_dropeffects) { - dst->AddDropeffect(dropeffect); + // Frames and iframes: + // If there are children, the fallback content has been rendered and should + // be used instead. For example, the fallback content may be rendered if + // there was an error loading an <object>. In that case, only expose the + // children. A node should not have both children and a child tree. + WebFrame* frame = WebFrame::FromFrameOwnerElement(element); + if (frame && !src.ChildCount()) + dst->child_routing_id = RenderFrame::GetRoutingIdForWebFrame(frame); +} + +void BlinkAXTreeSource::SerializeHTMLAttributes(WebAXObject src, + WebElement element, + AXContentNodeData* dst) const { + // TODO(ctguil): The tagName in WebKit is lower cased but + // HTMLElement::nodeName calls localNameUpper. Consider adding + // a WebElement method that returns the original lower cased tagName. + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kHtmlTag, + base::ToLowerASCII(element.TagName().Utf8())); + for (unsigned i = 0; i < element.AttributeCount(); ++i) { + std::string name = base::ToLowerASCII(element.AttributeLocalName(i).Utf8()); + if (name != "class") { // class already in kClassName. + std::string value = element.AttributeValue(i).Utf8(); + dst->html_attributes.push_back(std::make_pair(name, value)); } } + +// TODO(nektar): Turn off kHTMLAccessibilityMode for automation and Mac +// and remove ifdef. +#if defined(OS_WIN) || defined(OS_CHROMEOS) + if (dst->role == ax::mojom::Role::kMath && element.InnerHTML().length()) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kInnerHtml, + element.InnerHTML().Utf8()); + } +#endif } blink::WebDocument BlinkAXTreeSource::GetMainDocument() const { @@ -1253,31 +1340,36 @@ void BlinkAXTreeSource::AddImageAnnotations(blink::WebAXObject& src, return; } - // Reject images that are explicitly empty, or that have a name already. - // - // In the future, we may annotate some images that have a name - // if we think we can add additional useful information. + // Reject images that are explicitly empty, or that have a + // meaningful name already. ax::mojom::NameFrom name_from; blink::WebVector<WebAXObject> name_objects; blink::WebString web_name = src.GetName(name_from, name_objects); - // Normally we don't assign an annotation to an image if it already - // has a name. There are a few exceptions where we ignore the name. - bool treat_name_as_empty = false; + // If an image has a nonempty name, compute whether we should add an + // image annotation or not. + bool should_annotate_image_with_nonempty_name = false; // When visual debugging is enabled, the "title" attribute is set to a // string beginning with a "%". If the name comes from that string we // can ignore it, and treat the name as empty. if (image_annotation_debugging_ && base::StartsWith(web_name.Utf8(), "%", base::CompareCase::SENSITIVE)) - treat_name_as_empty = true; + should_annotate_image_with_nonempty_name = true; + + if (features::IsAugmentExistingImageLabelsEnabled()) { + // If the name consists of mostly stopwords, we can add an image + // annotations. See ax_image_stopwords.h for details. + if (image_annotator_->ImageNameHasMostlyStopwords(web_name.Utf8())) + should_annotate_image_with_nonempty_name = true; + } // If the image's name is explicitly empty, or if it has a name (and // we're not treating the name as empty), then it's ineligible for // an annotation. if ((name_from == ax::mojom::NameFrom::kAttributeExplicitlyEmpty || !web_name.IsEmpty()) && - !treat_name_as_empty) { + !should_annotate_image_with_nonempty_name) { dst->SetImageAnnotationStatus( ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation); return; @@ -1291,13 +1383,13 @@ void BlinkAXTreeSource::AddImageAnnotations(blink::WebAXObject& src, if (dst->role == ax::mojom::Role::kRootWebArea) { std::string filename = GURL(document().Url()).ExtractFileName(); if (base::StartsWith(dst_name, filename, base::CompareCase::SENSITIVE)) - treat_name_as_empty = true; + should_annotate_image_with_nonempty_name = true; } // |dst| may be a document or link containing an image. Skip annotating // it if it already has text other than whitespace. if (!base::ContainsOnlyChars(dst_name, base::kWhitespaceASCII) && - !treat_name_as_empty) { + !should_annotate_image_with_nonempty_name) { dst->SetImageAnnotationStatus( ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation); return; diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.h b/chromium/content/renderer/accessibility/blink_ax_tree_source.h index 1cfefe0cbe8..59783fb817e 100644 --- a/chromium/content/renderer/accessibility/blink_ax_tree_source.h +++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.h @@ -12,6 +12,7 @@ #include "base/optional.h" #include "content/common/ax_content_node_data.h" +#include "content/common/ax_content_tree_data.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document.h" #include "ui/accessibility/ax_mode.h" @@ -91,12 +92,6 @@ class BlinkAXTreeSource bool ShouldLoadInlineTextBoxes(const blink::WebAXObject& obj) const; void SetLoadInlineTextBoxesForId(int32_t id); - // Call this to enable populating the DOMNodeID for each node. This is - // currently only used for accessible PDF exporting. Warning, this is totally - // unrelated to the accessibility node ID, or the ID attribute for an HTML - // element. - void EnableDOMNodeIDs(); - // AXTreeSource implementation. bool GetTreeData(AXContentTreeData* tree_data) const override; blink::WebAXObject GetRoot() const override; @@ -131,6 +126,45 @@ class BlinkAXTreeSource return focus_; } + void SerializeBoundingBoxAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializePDFAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeSparseAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeNameAndDescriptionAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeValueAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeStateAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeStyleAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeInlineTextBoxAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeMarkerAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeLiveRegionAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeListAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeTableAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeScrollAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeChooserPopupAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeOtherScreenReaderAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeEditableTextAttributes(blink::WebAXObject src, + AXContentNodeData* dst) const; + void SerializeElementAttributes(blink::WebAXObject src, + blink::WebElement element, + AXContentNodeData* dst) const; + void SerializeHTMLAttributes(blink::WebAXObject src, + blink::WebElement element, + AXContentNodeData* dst) const; + blink::WebAXObject ComputeRoot() const; // Max length for attributes such as aria-label. @@ -157,11 +191,6 @@ class BlinkAXTreeSource // A set of IDs for which we should always load inline text boxes. std::set<int32_t> load_inline_text_boxes_ids_; - // Whether we should store Blink DOMNodeIds in the accessibility tree. - // Warning, this is totally unrelated to the accessibility node ID, or the ID - // attribute for an HTML element. - bool enable_dom_node_ids_ = false; - // The ID of the object to fetch image data for. int image_data_node_id_ = -1; diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.cc b/chromium/content/renderer/accessibility/render_accessibility_impl.cc index a504fc800b9..5ee61fd1adc 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_impl.cc +++ b/chromium/content/renderer/accessibility/render_accessibility_impl.cc @@ -17,12 +17,13 @@ #include "base/debug/crash_logging.h" #include "base/location.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/timer/elapsed_timer.h" #include "build/build_config.h" +#include "content/public/renderer/render_thread.h" #include "content/renderer/accessibility/ax_action_target_factory.h" #include "content/renderer/accessibility/ax_image_annotator.h" #include "content/renderer/accessibility/blink_ax_action_target.h" @@ -31,6 +32,8 @@ #include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_view_impl.h" #include "services/image_annotation/public/mojom/image_annotation.mojom.h" +#include "services/metrics/public/cpp/mojo_ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_builders.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_float_rect.h" #include "third_party/blink/public/web/web_document.h" @@ -57,6 +60,8 @@ using blink::WebView; namespace { +constexpr int kDelayForDeferredEvents = 350; + void SetAccessibilityCrashKey(ui::AXMode mode) { // Add a crash key with the ax_mode, to enable searching for top crashes that // occur when accessibility is turned on. This adds it for each renderer, @@ -125,7 +130,6 @@ void AXTreeSnapshotterImpl::SnapshotContentTree(ui::AXMode ax_mode, BlinkAXTreeSource tree_source(render_frame_, ax_mode); tree_source.SetRoot(root); - tree_source.EnableDOMNodeIDs(); ScopedFreezeBlinkAXTreeSource freeze(&tree_source); // The serializer returns an AXContentTreeUpdate, which can store a complete @@ -177,8 +181,12 @@ RenderAccessibilityImpl::RenderAccessibilityImpl( serializer_(&tree_source_), plugin_tree_source_(nullptr), last_scroll_offset_(gfx::Size()), - ack_pending_(false), + event_schedule_status_(EventScheduleStatus::kNotWaiting), reset_token_(0) { + mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> recorder; + content::RenderThread::Get()->BindHostReceiver( + recorder.InitWithNewPipeAndPassReceiver()); + ukm_recorder_ = std::make_unique<ukm::MojoUkmRecorder>(std::move(recorder)); WebView* web_view = render_frame_->GetRenderView()->GetWebView(); WebSettings* settings = web_view->GetSettings(); @@ -195,6 +203,16 @@ RenderAccessibilityImpl::RenderAccessibilityImpl( settings->SetInlineTextBoxAccessibilityEnabled(true); #endif +#if defined(OS_MACOSX) + // aria-modal currently prunes the accessibility tree on Mac only. + settings->SetAriaModalPrunesAXTree(true); +#endif + + if (render_frame_->IsMainFrame()) + event_schedule_mode_ = EventScheduleMode::kDeferEvents; + else + event_schedule_mode_ = EventScheduleMode::kProcessEventsImmediately; + const WebDocument& document = GetMainDocument(); if (!document.IsNull()) { ax_context_ = std::make_unique<WebAXContext>(document); @@ -222,9 +240,14 @@ void RenderAccessibilityImpl::DidCreateNewDocument() { } void RenderAccessibilityImpl::DidCommitProvisionalLoad( - bool is_same_document_navigation, ui::PageTransition transition) { has_injected_stylesheet_ = false; + + // If we have events scheduled, but not sent, cancel them + CancelScheduledEvents(); + // Defer events during initial page load. + event_schedule_mode_ = EventScheduleMode::kDeferEvents; + // Remove the image annotator if the page is loading and it was added for // the one-shot image annotation (i.e. AXMode for image annotation is not // set). @@ -283,46 +306,61 @@ void RenderAccessibilityImpl::AccessibilityModeChanged(const ui::AXMode& mode) { } void RenderAccessibilityImpl::HitTest( - const ui::AXActionData& action_data, + const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback) { - // This method should be called exclusively for kHitTest actions. - DCHECK_EQ(action_data.action, ax::mojom::Action::kHitTest); - DCHECK_NE(action_data.hit_test_event_to_fire, ax::mojom::Event::kNone); - WebAXObject ax_object; const WebDocument& document = GetMainDocument(); if (!document.IsNull()) { auto root_obj = WebAXObject::FromWebDocument(document); if (root_obj.UpdateLayoutAndCheckValidity()) - ax_object = root_obj.HitTest(action_data.target_point); + ax_object = root_obj.HitTest(point); } // Return if no attached accessibility object was found for the main document. if (ax_object.IsDetached()) { - std::move(callback).Run(/*child_frame_hit_test_info=*/nullptr); + std::move(callback).Run(/*hit_test_response=*/nullptr); return; } - // If the object that was hit has a child frame, we have to send a message - // back to the browser to do the hit test in the child frame, recursively. + // If the result was in the same frame, return the result. AXContentNodeData data; ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); tree_source_.SerializeNode(ax_object, &data); if (data.child_routing_id == MSG_ROUTING_NONE) { - // Otherwise, send an event on the node that was hit. - const std::vector<ui::AXEventIntent> intents; - HandleAXEvent(ui::AXEvent( - ax_object.AxID(), action_data.hit_test_event_to_fire, - ax::mojom::EventFrom::kAction, intents, action_data.request_id)); - - // The mojo message still needs a reply. - std::move(callback).Run(/*child_frame_hit_test_info=*/nullptr); + // Optionally fire an event, if requested to. This is a good fit for + // features like touch exploration on Android, Chrome OS, and + // possibly other platforms - if the user explore a particular point, + // we fire a hover event on the nearest object under the point. + // + // Avoid using this mechanism to fire a particular sentinel event + // and then listen for that event to associate it with the hit test + // request. Instead, the mojo reply should be used directly. + if (event_to_fire != ax::mojom::Event::kNone) { + const std::vector<ui::AXEventIntent> intents; + HandleAXEvent(ui::AXEvent(ax_object.AxID(), event_to_fire, + ax::mojom::EventFrom::kAction, intents, + request_id)); + } + + // Reply with the result. + const auto& frame_token = render_frame_->GetWebFrame()->GetFrameToken(); + std::move(callback).Run( + mojom::HitTestResponse::New(frame_token, point, ax_object.AxID())); return; } - gfx::Point transformed_point = action_data.target_point; - bool is_remote_frame = RenderFrameProxy::FromRoutingID(data.child_routing_id); - if (is_remote_frame) { + // The result was in a child frame. Reply so that the + // client can do a hit test on the child frame recursively. + // If it's a remote frame, transform the point into the child frame's + // coordinate system. + gfx::Point transformed_point = point; + blink::WebFrame* child_frame = + blink::WebFrame::FromFrameOwnerElement(ax_object.GetNode()); + DCHECK(child_frame); + + if (child_frame->IsWebRemoteFrame()) { // Remote frames don't have access to the information from the visual // viewport regarding the visual viewport offset, so we adjust the // coordinates before sending them to the remote renderer. @@ -337,12 +375,8 @@ void RenderAccessibilityImpl::HitTest( gfx::Rect(rect).OffsetFromOrigin(); } - // Signal to the caller that we haven't handled this hit test yet, and that - // a new one will need to be performed over the child frame found. - std::move(callback).Run(mojom::ChildFrameHitTestInfo::New( - data.child_routing_id, transformed_point, - action_data.hit_test_event_to_fire)); - return; + std::move(callback).Run(mojom::HitTestResponse::New( + child_frame->GetFrameToken(), transformed_point, ax_object.AxID())); } void RenderAccessibilityImpl::PerformAction(const ui::AXActionData& data) { @@ -354,6 +388,9 @@ void RenderAccessibilityImpl::PerformAction(const ui::AXActionData& data) { if (!root.UpdateLayoutAndCheckValidity()) return; + // If an action was requested, we no longer want to defer events. + event_schedule_mode_ = EventScheduleMode::kProcessEventsImmediately; + std::unique_ptr<ui::AXActionTarget> target = AXActionTargetFactory::CreateFromNodeId(document, plugin_tree_source_, data.target_node_id); @@ -491,7 +528,7 @@ void RenderAccessibilityImpl::MarkWebAXObjectDirty(const WebAXObject& obj, if (subtree) serializer_.InvalidateSubtree(obj); - ScheduleSendAccessibilityEventsIfNeeded(); + ScheduleSendPendingAccessibilityEvents(); } void RenderAccessibilityImpl::HandleAXEvent(const ui::AXEvent& event) { @@ -549,10 +586,37 @@ void RenderAccessibilityImpl::HandleAXEvent(const ui::AXEvent& event) { } pending_events_.push_back(event); - ScheduleSendAccessibilityEventsIfNeeded(); + // Once we get the first load, we should no longer defer events. + if (event.event_type == ax::mojom::Event::kLoadComplete) + event_schedule_mode_ = EventScheduleMode::kProcessEventsImmediately; + + ScheduleSendPendingAccessibilityEvents(); +} + +bool RenderAccessibilityImpl::ShouldSerializeNodeForEvent( + const WebAXObject& obj, + const ui::AXEvent& event) const { + if (obj.IsDetached()) + return false; + + if (event.event_type == ax::mojom::Event::kTextSelectionChanged && + !obj.IsNativeTextControl()) { + // Selection changes on non-native text controls cause no change to the + // control node's data. + // + // Selection offsets exposed via kTextSelStart and kTextSelEnd are only used + // for plain text controls, (input of a text field type, and textarea). Rich + // editable areas, such as contenteditables, use AXTreeData. + // + // TODO(nektar): Remove kTextSelStart and kTextSelEnd from the renderer. + return false; + } + + return true; } -void RenderAccessibilityImpl::ScheduleSendAccessibilityEventsIfNeeded() { +void RenderAccessibilityImpl::ScheduleSendPendingAccessibilityEvents( + bool scheduling_from_task) { // Don't send accessibility events for frames that are not in the frame tree // yet (i.e., provisional frames used for remote-to-local navigations, which // haven't committed yet). Doing so might trigger layout, which may not work @@ -561,16 +625,56 @@ void RenderAccessibilityImpl::ScheduleSendAccessibilityEventsIfNeeded() { if (!render_frame_ || !render_frame_->in_frame_tree()) return; - if (!ack_pending_ && !weak_factory_.HasWeakPtrs()) { - // When no accessibility events are in-flight post a task to send - // the events to the browser. We use PostTask so that we can queue - // up additional events. - render_frame_->GetTaskRunner(blink::TaskType::kInternalDefault) - ->PostTask(FROM_HERE, - base::BindOnce( - &RenderAccessibilityImpl::SendPendingAccessibilityEvents, - weak_factory_.GetWeakPtr())); + switch (event_schedule_status_) { + case EventScheduleStatus::kScheduledDeferred: + if (event_schedule_mode_ == + EventScheduleMode::kProcessEventsImmediately) { + // Cancel scheduled deferred events so we can schedule events to be + // sent immediately. + CancelScheduledEvents(); + break; + } + // We have already scheduled a task to send pending events. + return; + case EventScheduleStatus::kScheduledImmediate: + // The send pending events task have been scheduled, but has not started. + return; + case EventScheduleStatus::kWaitingForAck: + // Events have been sent, wait for ack. + return; + case EventScheduleStatus::kNotWaiting: + // Once the events have been handled, we schedule the pending events from + // that task. In this case, there would be a weak ptr still in use. + if (!scheduling_from_task && + weak_factory_for_pending_events_.HasWeakPtrs()) + return; + break; } + + base::TimeDelta delay = base::TimeDelta::FromMilliseconds(0); + switch (event_schedule_mode_) { + case EventScheduleMode::kDeferEvents: + event_schedule_status_ = EventScheduleStatus::kScheduledDeferred; + // During page load, process changes on a delay so that they occur in + // larger batches, which helps improve efficiency of page loads. + delay = base::TimeDelta::FromMilliseconds(kDelayForDeferredEvents); + break; + case EventScheduleMode::kProcessEventsImmediately: + event_schedule_status_ = EventScheduleStatus::kScheduledImmediate; + delay = base::TimeDelta::FromMilliseconds(0); + break; + } + + // When no accessibility events are in-flight post a task to send + // the events to the browser. We use PostTask so that we can queue + // up additional events. + render_frame_->GetTaskRunner(blink::TaskType::kInternalDefault) + ->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &RenderAccessibilityImpl::SendPendingAccessibilityEvents, + weak_factory_for_pending_events_.GetWeakPtr()), + delay); } int RenderAccessibilityImpl::GenerateAXID() { @@ -587,37 +691,31 @@ void RenderAccessibilityImpl::SetPluginTreeSource( } void RenderAccessibilityImpl::OnPluginRootNodeUpdated() { - // Search the accessibility tree for an EMBED element and post a + // Search the accessibility tree for plugin's root object and post a // children changed notification on it to force it to update the // plugin accessibility tree. - - ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); - WebAXObject root = tree_source_.GetRoot(); - if (!root.UpdateLayoutAndCheckValidity()) + WebAXObject obj = GetPluginRoot(); + if (obj.IsNull()) return; - base::queue<WebAXObject> objs_to_explore; - objs_to_explore.push(root); - while (objs_to_explore.size()) { - WebAXObject obj = objs_to_explore.front(); - objs_to_explore.pop(); + HandleAXEvent(ui::AXEvent(obj.AxID(), ax::mojom::Event::kChildrenChanged)); +} - WebNode node = obj.GetNode(); - if (!node.IsNull() && node.IsElementNode()) { - WebElement element = node.To<WebElement>(); - if (element.HasHTMLTagName("embed")) { - HandleAXEvent( - ui::AXEvent(obj.AxID(), ax::mojom::Event::kChildrenChanged)); - break; - } - } +void RenderAccessibilityImpl::ShowPluginContextMenu() { + // Search the accessibility tree for plugin's root object and invoke + // ShowContextMenu() on it to show context menu for plugin. + WebAXObject obj = GetPluginRoot(); + if (obj.IsNull()) + return; - // Explore children of this object. - std::vector<WebAXObject> children; - tree_source_.GetChildren(obj, &children); - for (size_t i = 0; i < children.size(); ++i) - objs_to_explore.push(children[i]); - } + const WebDocument& document = GetMainDocument(); + if (document.IsNull()) + return; + + std::unique_ptr<ui::AXActionTarget> target = + AXActionTargetFactory::CreateFromNodeId(document, plugin_tree_source_, + obj.AxID()); + target->ShowContextMenu(); } WebDocument RenderAccessibilityImpl::GetMainDocument() { @@ -633,7 +731,10 @@ std::string RenderAccessibilityImpl::GetLanguage() { void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { TRACE_EVENT0("accessibility", "RenderAccessibilityImpl::SendPendingAccessibilityEvents"); + base::ElapsedTimer timer_; + // Clear status here in case we return early. + event_schedule_status_ = EventScheduleStatus::kNotWaiting; WebDocument document = GetMainDocument(); if (document.IsNull()) return; @@ -641,8 +742,6 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { if (pending_events_.empty() && dirty_objects_.empty()) return; - ack_pending_ = true; - // Make a copy of the events, because it's possible that // actions inside this loop will cause more events to be // queued up. @@ -660,7 +759,8 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { // If there's a layout complete message, we need to send location changes. bool had_layout_complete_messages = false; - // If there's a load complete message, we need to send image metrics. + // If there's a load complete message, we need to change the event schedule + // mode. bool had_load_complete_messages = false; ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); @@ -670,7 +770,7 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { page_language_ = root.Language().Utf8(); // Loop over each event and generate an updated event message. - for (auto& event : src_events) { + for (ui::AXEvent& event : src_events) { if (event.event_type == ax::mojom::Event::kLayoutComplete) had_layout_complete_messages = true; @@ -683,8 +783,22 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { if (!obj.UpdateLayoutAndCheckValidity()) continue; + // Make sure it's a descendant of our root node - exceptions include the + // scroll area that's the parent of the main document (we ignore it), and + // possibly nodes attached to a different document. + if (!tree_source_.IsInTree(obj)) + continue; + // If it's ignored, find the first ancestor that's not ignored. - while (!obj.IsDetached() && obj.AccessibilityIsIgnored()) { + // + // Note that "IsDetached()" also calls "IsNull()". Additionally, + // "ParentObject()" always gets the first ancestor that is included in tree + // (ignored or unignored), so it will never return objects that are not + // included in the tree at all. + if (!obj.AccessibilityIsIncludedInTree()) + obj = obj.ParentObject(); + for (; !obj.IsDetached() && obj.AccessibilityIsIgnored(); + obj = obj.ParentObject()) { // There are 3 states of nodes that we care about here. // (x) Unignored, included in tree // [x] Ignored, included in tree @@ -702,9 +816,6 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { // change, but we must also re-serialize [2] since its children // have changed. <1> was never part of the ax tree, and therefore // does not need to be serialized. - // - // So on the way to the Unignored parent, ancestors that are - // included in the tree must also be serialized. // Note that [3] will be serialized to (3) during : // |AXTreeSerializer<>::SerializeChangedNodes| when node [2] is // being serialized, since it will detect the Ignored state had @@ -713,30 +824,28 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { // Similarly, during Event::kTextChanged, if any Ignored, // but included in tree ancestor uses NameFrom::kContents, // they must also be re-serialized in case the name changed. - if (obj.AccessibilityIsIncludedInTree()) { + if (ShouldSerializeNodeForEvent(obj, event)) { DirtyObject dirty_object; dirty_object.obj = obj; dirty_object.event_from = event.event_from; + dirty_object.event_intents = event.event_intents; dirty_objects.push_back(dirty_object); } - obj = obj.ParentObject(); } - // Make sure it's a descendant of our root node - exceptions include the - // scroll area that's the parent of the main document (we ignore it), and - // possibly nodes attached to a different document. - if (!tree_source_.IsInTree(obj)) - continue; - events.push_back(event); VLOG(1) << "Accessibility event: " << ui::ToString(event.event_type) << " on node id " << event.id; - DirtyObject dirty_object; - dirty_object.obj = obj; - dirty_object.event_from = event.event_from; - dirty_objects.push_back(dirty_object); + // Some events don't cause any changes to their associated objects. + if (ShouldSerializeNodeForEvent(obj, event)) { + DirtyObject dirty_object; + dirty_object.obj = obj; + dirty_object.event_from = event.event_from; + dirty_object.event_intents = event.event_intents; + dirty_objects.push_back(dirty_object); + } } // Popups have a document lifecycle managed separately from the main document @@ -786,6 +895,7 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { AXContentTreeUpdate update; update.event_from = dirty_objects[i].event_from; + update.event_intents = dirty_objects[i].event_intents; // If there's a plugin, force the tree data to be generated in every // message so the plugin can merge its own tree data changes. if (plugin_tree_source_) @@ -812,26 +922,31 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { updates.push_back(update); - if (had_load_complete_messages) - RecordImageMetrics(&update); - VLOG(1) << "Accessibility tree update:\n" << update.ToString(); } + event_schedule_status_ = EventScheduleStatus::kWaitingForAck; render_accessibility_manager_->HandleAccessibilityEvents( updates, events, reset_token_, base::BindOnce(&RenderAccessibilityImpl::OnAccessibilityEventsHandled, - weak_factory_.GetWeakPtr())); + weak_factory_for_pending_events_.GetWeakPtr())); reset_token_ = 0; if (had_layout_complete_messages) SendLocationChanges(); - if (had_load_complete_messages) + if (had_load_complete_messages) { has_injected_stylesheet_ = false; + event_schedule_mode_ = EventScheduleMode::kProcessEventsImmediately; + } if (image_annotation_debugging_) AddImageAnnotationDebuggingAttributes(updates); + + ukm::builders::Accessibility_Renderer(document.GetUkmSourceId()) + .SetCpuTime_SendPendingAccessibilityEvents( + timer_.Elapsed().InMilliseconds()) + .Record(ukm_recorder_.get()); } void RenderAccessibilityImpl::SendLocationChanges() { @@ -889,9 +1004,16 @@ void RenderAccessibilityImpl::SendLocationChanges() { } void RenderAccessibilityImpl::OnAccessibilityEventsHandled() { - DCHECK(ack_pending_); - ack_pending_ = false; - SendPendingAccessibilityEvents(); + DCHECK_EQ(event_schedule_status_, EventScheduleStatus::kWaitingForAck); + event_schedule_status_ = EventScheduleStatus::kNotWaiting; + switch (event_schedule_mode_) { + case EventScheduleMode::kDeferEvents: + ScheduleSendPendingAccessibilityEvents(true); + break; + case EventScheduleMode::kProcessEventsImmediately: + SendPendingAccessibilityEvents(); + break; + } } void RenderAccessibilityImpl::OnLoadInlineTextBoxes( @@ -1083,51 +1205,6 @@ void RenderAccessibilityImpl::Scroll(const ui::AXActionTarget* target, target->SetScrollOffset(gfx::Point(x, y)); } -void RenderAccessibilityImpl::RecordImageMetrics(AXContentTreeUpdate* update) { - if (!GetAccessibilityMode().has_mode(ui::AXMode::kScreenReader)) - return; - float scale_factor = render_frame_->GetDeviceScaleFactor(); - for (size_t i = 0; i < update->nodes.size(); ++i) { - ui::AXNodeData& node_data = update->nodes[i]; - if (node_data.role != ax::mojom::Role::kImage) - continue; - // Convert to DIPs based on screen scale factor. - int width = node_data.relative_bounds.bounds.width() / scale_factor; - int height = node_data.relative_bounds.bounds.height() / scale_factor; - if (width == 0 || height == 0) - continue; - // We log the min size in a histogram with a max of 10000, so set a ceiling - // of 10000 on min_size. - int min_size = std::min({width, height, 10000}); - int max_size = std::max(width, height); - // The ratio is always the smaller divided by the larger so as not to go - // over 100%. - int ratio = min_size * 100.0 / max_size; - const std::string name = - node_data.GetStringAttribute(ax::mojom::StringAttribute::kName); - bool explicitly_empty = node_data.GetNameFrom() == - ax::mojom::NameFrom::kAttributeExplicitlyEmpty; - if (!name.empty()) { - UMA_HISTOGRAM_PERCENTAGE( - "Accessibility.ScreenReader.Image.SizeRatio.Labeled", ratio); - UMA_HISTOGRAM_COUNTS_10000( - "Accessibility.ScreenReader.Image.MinSize.Labeled", min_size); - } else if (explicitly_empty) { - UMA_HISTOGRAM_PERCENTAGE( - "Accessibility.ScreenReader.Image.SizeRatio.ExplicitlyUnlabeled", - ratio); - UMA_HISTOGRAM_COUNTS_10000( - "Accessibility.ScreenReader.Image.MinSize.ExplicitlyUnlabeled", - min_size); - } else { - UMA_HISTOGRAM_PERCENTAGE( - "Accessibility.ScreenReader.Image.SizeRatio.Unlabeled", ratio); - UMA_HISTOGRAM_COUNTS_10000( - "Accessibility.ScreenReader.Image.MinSize.Unlabeled", min_size); - } - } -} - void RenderAccessibilityImpl::AddImageAnnotationDebuggingAttributes( const std::vector<AXContentTreeUpdate>& updates) { DCHECK(image_annotation_debugging_); @@ -1208,4 +1285,52 @@ blink::WebDocument RenderAccessibilityImpl::GetPopupDocument() { return WebDocument(); } +WebAXObject RenderAccessibilityImpl::GetPluginRoot() { + ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); + WebAXObject root = tree_source_.GetRoot(); + if (!root.UpdateLayoutAndCheckValidity()) + return WebAXObject(); + + base::queue<WebAXObject> objs_to_explore; + objs_to_explore.push(root); + while (objs_to_explore.size()) { + WebAXObject obj = objs_to_explore.front(); + objs_to_explore.pop(); + + WebNode node = obj.GetNode(); + if (!node.IsNull() && node.IsElementNode()) { + WebElement element = node.To<WebElement>(); + if (element.HasHTMLTagName("embed")) { + return obj; + } + } + + // Explore children of this object. + std::vector<WebAXObject> children; + tree_source_.GetChildren(obj, &children); + for (const auto& child : children) + objs_to_explore.push(child); + } + + return WebAXObject(); +} + +void RenderAccessibilityImpl::CancelScheduledEvents() { + switch (event_schedule_status_) { + case EventScheduleStatus::kScheduledDeferred: + case EventScheduleStatus::kScheduledImmediate: // Fallthrough + weak_factory_for_pending_events_.InvalidateWeakPtrs(); + event_schedule_status_ = EventScheduleStatus::kNotWaiting; + break; + case EventScheduleStatus::kWaitingForAck: + case EventScheduleStatus::kNotWaiting: // Fallthrough + break; + } +} + +RenderAccessibilityImpl::DirtyObject::DirtyObject() = default; +RenderAccessibilityImpl::DirtyObject::DirtyObject(const DirtyObject& other) = + default; +RenderAccessibilityImpl::DirtyObject::~DirtyObject() = default; + } // namespace content diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.h b/chromium/content/renderer/accessibility/render_accessibility_impl.h index 47814c1adcc..1275797c723 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_impl.h +++ b/chromium/content/renderer/accessibility/render_accessibility_impl.h @@ -12,6 +12,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "content/common/ax_content_node_data.h" +#include "content/common/ax_content_tree_data.h" +#include "content/common/ax_content_tree_update.h" #include "content/common/content_export.h" #include "content/common/render_accessibility.mojom.h" #include "content/public/renderer/plugin_ax_tree_source.h" @@ -37,6 +39,10 @@ class AXActionTarget; struct AXEvent; } +namespace ukm { +class MojoUkmRecorder; +} + namespace content { class AXImageAnnotator; @@ -115,14 +121,16 @@ class CONTENT_EXPORT RenderAccessibilityImpl : public RenderAccessibility, int GenerateAXID() override; void SetPluginTreeSource(PluginAXTreeSource* source) override; void OnPluginRootNodeUpdated() override; + void ShowPluginContextMenu() override; // RenderFrameObserver implementation. void DidCreateNewDocument() override; - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override; + void DidCommitProvisionalLoad(ui::PageTransition transition) override; void AccessibilityModeChanged(const ui::AXMode& mode) override; - void HitTest(const ui::AXActionData& action_data, + void HitTest(const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback); void PerformAction(const ui::AXActionData& data); void Reset(int32_t reset_token); @@ -151,8 +159,25 @@ class CONTENT_EXPORT RenderAccessibilityImpl : public RenderAccessibility, private: struct DirtyObject { + DirtyObject(); + DirtyObject(const DirtyObject& other); + ~DirtyObject(); blink::WebAXObject obj; ax::mojom::EventFrom event_from; + std::vector<ui::AXEventIntent> event_intents; + }; + + enum class EventScheduleMode { kDeferEvents, kProcessEventsImmediately }; + + enum class EventScheduleStatus { + // Events have been scheduled with a delay, but have not been sent. + kScheduledDeferred, + // Events have been scheduled without a delay, but have not been sent. + kScheduledImmediate, + // Events have been sent, waiting for callback. + kWaitingForAck, + // Events are not scheduled and we are not waiting for an ack. + kNotWaiting }; // Callback that will be called from the browser upon handling the message @@ -183,14 +208,28 @@ class CONTENT_EXPORT RenderAccessibilityImpl : public RenderAccessibility, void Scroll(const ui::AXActionTarget* target, ax::mojom::Action scroll_action); - void ScheduleSendAccessibilityEventsIfNeeded(); - void RecordImageMetrics(AXContentTreeUpdate* update); + + // Whether an event should mark its associated object dirty. + bool ShouldSerializeNodeForEvent(const blink::WebAXObject& obj, + const ui::AXEvent& event) const; + + // If we are calling this from a task, scheduling is allowed even if there is + // a running task + void ScheduleSendPendingAccessibilityEvents( + bool scheduling_from_task = false); void AddImageAnnotationDebuggingAttributes( const std::vector<AXContentTreeUpdate>& updates); // Returns the document for the active popup if any. blink::WebDocument GetPopupDocument(); + // Searches the accessibility tree for plugin's root object and returns it. + // Returns an empty WebAXObject if no root object is present. + blink::WebAXObject GetPluginRoot(); + + // Cancels scheduled events that are not yet in flight + void CancelScheduledEvents(); + // The RenderAccessibilityManager that owns us. RenderAccessibilityManager* render_accessibility_manager_; @@ -233,8 +272,8 @@ class CONTENT_EXPORT RenderAccessibilityImpl : public RenderAccessibility, // is fixed. gfx::Size last_scroll_offset_; - // Set if we are waiting for an accessibility event ack. - bool ack_pending_; + // Current event scheduling status + EventScheduleStatus event_schedule_status_; // Nonzero if the browser requested we reset the accessibility state. // We need to return this token in the next IPC. @@ -244,6 +283,9 @@ class CONTENT_EXPORT RenderAccessibilityImpl : public RenderAccessibility, // (only when debugging flags are enabled, never under normal circumstances). bool has_injected_stylesheet_ = false; + // We defer events to improve performance during the initial page load. + EventScheduleMode event_schedule_mode_; + // Whether we should highlight annotation results visually on the page // for debugging. bool image_annotation_debugging_ = false; @@ -251,8 +293,11 @@ class CONTENT_EXPORT RenderAccessibilityImpl : public RenderAccessibility, // The specified page language, or empty if unknown. std::string page_language_; + std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder_; + // So we can queue up tasks to be executed later. - base::WeakPtrFactory<RenderAccessibilityImpl> weak_factory_{this}; + base::WeakPtrFactory<RenderAccessibilityImpl> + weak_factory_for_pending_events_{this}; friend class AXImageAnnotatorTest; friend class PluginActionHandlingTest; diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc b/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc index 3781c691064..1c3dec29b14 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc +++ b/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc @@ -17,6 +17,7 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "build/build_config.h" +#include "content/common/ax_content_tree_update.h" #include "content/common/frame_messages.h" #include "content/common/render_accessibility.mojom-test-utils.h" #include "content/common/render_accessibility.mojom.h" @@ -246,6 +247,42 @@ class RenderAccessibilityImplTest : public RenderViewTest { } ~RenderAccessibilityImplTest() override = default; + void ScheduleSendPendingAccessibilityEvents() { + GetRenderAccessibilityImpl()->ScheduleSendPendingAccessibilityEvents(); + } + + void ExpectScheduleStatusScheduledDeferred() { + EXPECT_EQ(GetRenderAccessibilityImpl()->event_schedule_status_, + RenderAccessibilityImpl::EventScheduleStatus::kScheduledDeferred); + } + + void ExpectScheduleStatusScheduledImmediate() { + EXPECT_EQ( + GetRenderAccessibilityImpl()->event_schedule_status_, + RenderAccessibilityImpl::EventScheduleStatus::kScheduledImmediate); + } + + void ExpectScheduleStatusWaitingForAck() { + EXPECT_EQ(GetRenderAccessibilityImpl()->event_schedule_status_, + RenderAccessibilityImpl::EventScheduleStatus::kWaitingForAck); + } + + void ExpectScheduleStatusNotWaiting() { + EXPECT_EQ(GetRenderAccessibilityImpl()->event_schedule_status_, + RenderAccessibilityImpl::EventScheduleStatus::kNotWaiting); + } + + void ExpectScheduleModeDeferEvents() { + EXPECT_EQ(GetRenderAccessibilityImpl()->event_schedule_mode_, + RenderAccessibilityImpl::EventScheduleMode::kDeferEvents); + } + + void ExpectScheduleModeProcessEventsImmediately() { + EXPECT_EQ( + GetRenderAccessibilityImpl()->event_schedule_mode_, + RenderAccessibilityImpl::EventScheduleMode::kProcessEventsImmediately); + } + protected: RenderViewImpl* view() { return static_cast<RenderViewImpl*>(view_); @@ -404,6 +441,62 @@ TEST_F(RenderAccessibilityImplTest, SendFullAccessibilityTreeOnReload) { EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser()); } +TEST_F(RenderAccessibilityImplTest, TestDeferred) { + constexpr char html[] = R"HTML( + <body> + <div> + a + </div> + </body> + )HTML"; + LoadHTML(html); + task_environment_.RunUntilIdle(); + + // We should have had load complete, causing us to send subsequent events + // without delay. + ExpectScheduleStatusNotWaiting(); + ExpectScheduleModeProcessEventsImmediately(); + + // Simulate a page load to test deferred behavior. + GetRenderAccessibilityImpl()->DidCommitProvisionalLoad( + ui::PageTransition::PAGE_TRANSITION_LINK); + ClearHandledUpdates(); + WebDocument document = GetMainFrame()->GetDocument(); + EXPECT_FALSE(document.IsNull()); + WebAXObject root_obj = WebAXObject::FromWebDocument(document); + EXPECT_FALSE(root_obj.IsNull()); + + // No events should have been scheduled or sent. + ExpectScheduleStatusNotWaiting(); + ExpectScheduleModeDeferEvents(); + + // Send an event, it should be scheduled with a delay. + GetRenderAccessibilityImpl()->HandleAXEvent( + ui::AXEvent(root_obj.AxID(), ax::mojom::Event::kLiveRegionChanged)); + ExpectScheduleStatusScheduledDeferred(); + ExpectScheduleModeDeferEvents(); + + task_environment_.RunUntilIdle(); + // Ensure event is not sent as it is scheduled with a delay. + ExpectScheduleStatusScheduledDeferred(); + ExpectScheduleModeDeferEvents(); + + // Perform action, causing immediate event processing. + ui::AXActionData action; + action.action = ax::mojom::Action::kFocus; + GetRenderAccessibilityImpl()->PerformAction(action); + ScheduleSendPendingAccessibilityEvents(); + + // Ensure task has been scheduled without delay. + ExpectScheduleStatusScheduledImmediate(); + ExpectScheduleModeProcessEventsImmediately(); + + task_environment_.RunUntilIdle(); + // Event has been sent, no longer waiting on ack. + ExpectScheduleStatusNotWaiting(); + ExpectScheduleModeProcessEventsImmediately(); +} + TEST_F(RenderAccessibilityImplTest, HideAccessibilityObject) { // Test RenderAccessibilityImpl and make sure it sends the // proper event to the browser when an object in the tree diff --git a/chromium/content/renderer/accessibility/render_accessibility_manager.cc b/chromium/content/renderer/accessibility/render_accessibility_manager.cc index 2278b175dec..06eb5da41a2 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_manager.cc +++ b/chromium/content/renderer/accessibility/render_accessibility_manager.cc @@ -69,10 +69,13 @@ void RenderAccessibilityManager::FatalError() { } void RenderAccessibilityManager::HitTest( - const ui::AXActionData& action_data, + const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback) { DCHECK(render_accessibility_); - render_accessibility_->HitTest(action_data, std::move(callback)); + render_accessibility_->HitTest(point, event_to_fire, request_id, + std::move(callback)); } void RenderAccessibilityManager::PerformAction(const ui::AXActionData& data) { diff --git a/chromium/content/renderer/accessibility/render_accessibility_manager.h b/chromium/content/renderer/accessibility/render_accessibility_manager.h index 57ebb7d7311..516c07bbd57 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_manager.h +++ b/chromium/content/renderer/accessibility/render_accessibility_manager.h @@ -9,6 +9,7 @@ #include "base/macros.h" #include "content/common/ax_content_node_data.h" +#include "content/common/ax_content_tree_update.h" #include "content/common/content_export.h" #include "content/common/render_accessibility.mojom.h" #include "mojo/public/cpp/bindings/associated_receiver.h" @@ -60,7 +61,9 @@ class CONTENT_EXPORT RenderAccessibilityManager // mojom::RenderAccessibility implementation. void SetMode(uint32_t ax_mode) override; void FatalError() override; - void HitTest(const ui::AXActionData& action_data, + void HitTest(const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback) override; void PerformAction(const ui::AXActionData& data) override; void Reset(int32_t reset_token) override; diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink_impl.cc index d002a87ab24..e8d7c94e41e 100644 --- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/android/synchronous_layer_tree_frame_sink.h" +#include "content/renderer/android/synchronous_layer_tree_frame_sink_impl.h" #include <vector> @@ -100,7 +100,7 @@ class SoftwareCompositorFrameSinkClient } // namespace -class SynchronousLayerTreeFrameSink::SoftwareOutputSurface +class SynchronousLayerTreeFrameSinkImpl::SoftwareOutputSurface : public viz::OutputSurface { public: SoftwareOutputSurface(std::unique_ptr<SoftwareDevice> software_device) @@ -137,20 +137,19 @@ class SynchronousLayerTreeFrameSink::SoftwareOutputSurface gpu::MemoryTracker* GetMemoryTracker() override { return nullptr; } }; -base::TimeDelta SynchronousLayerTreeFrameSink::StubDisplayClient:: +base::TimeDelta SynchronousLayerTreeFrameSinkImpl::StubDisplayClient:: GetPreferredFrameIntervalForFrameSinkId( const viz::FrameSinkId& id, viz::mojom::CompositorFrameSinkType* type) { return viz::BeginFrameArgs::MinInterval(); } -SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink( +SynchronousLayerTreeFrameSinkImpl::SynchronousLayerTreeFrameSinkImpl( scoped_refptr<viz::ContextProvider> context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, IPC::Sender* sender, - int routing_id, uint32_t layer_tree_frame_sink_id, std::unique_ptr<viz::BeginFrameSource> synthetic_begin_frame_source, SynchronousCompositorRegistry* registry, @@ -159,11 +158,10 @@ SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink( compositor_frame_sink_remote, mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> client_receiver) - : cc::LayerTreeFrameSink(std::move(context_provider), - std::move(worker_context_provider), - std::move(compositor_task_runner), - gpu_memory_buffer_manager), - routing_id_(routing_id), + : SynchronousLayerTreeFrameSink(std::move(context_provider), + std::move(worker_context_provider), + std::move(compositor_task_runner), + gpu_memory_buffer_manager), layer_tree_frame_sink_id_(layer_tree_frame_sink_id), registry_(registry), sender_(sender), @@ -181,14 +179,15 @@ SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink( gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; } -SynchronousLayerTreeFrameSink::~SynchronousLayerTreeFrameSink() = default; +SynchronousLayerTreeFrameSinkImpl::~SynchronousLayerTreeFrameSinkImpl() = + default; -void SynchronousLayerTreeFrameSink::SetSyncClient( +void SynchronousLayerTreeFrameSinkImpl::SetSyncClient( SynchronousLayerTreeFrameSinkClient* compositor) { sync_client_ = compositor; } -bool SynchronousLayerTreeFrameSink::BindToClient( +bool SynchronousLayerTreeFrameSinkImpl::BindToClient( cc::LayerTreeFrameSinkClient* sink_client) { DCHECK(CalledOnValidThread()); if (!cc::LayerTreeFrameSink::BindToClient(sink_client)) @@ -216,9 +215,9 @@ bool SynchronousLayerTreeFrameSink::BindToClient( client_->SetMemoryPolicy(memory_policy_); client_->SetTreeActivationCallback(base::BindRepeating( - &SynchronousLayerTreeFrameSink::DidActivatePendingTree, + &SynchronousLayerTreeFrameSinkImpl::DidActivatePendingTree, base::Unretained(this))); - registry_->RegisterLayerTreeFrameSink(routing_id_, this); + registry_->RegisterLayerTreeFrameSink(this); software_frame_sink_client_ = std::make_unique<SoftwareCompositorFrameSinkClient>(); @@ -256,7 +255,7 @@ bool SynchronousLayerTreeFrameSink::BindToClient( return true; } -void SynchronousLayerTreeFrameSink::DetachFromClient() { +void SynchronousLayerTreeFrameSinkImpl::DetachFromClient() { DCHECK(CalledOnValidThread()); client_->SetBeginFrameSource(nullptr); // Destroy the begin frame source on the same thread it was bound on. @@ -264,7 +263,7 @@ void SynchronousLayerTreeFrameSink::DetachFromClient() { external_begin_frame_source_ = nullptr; if (sync_client_) sync_client_->SinkDestroyed(); - registry_->UnregisterLayerTreeFrameSink(routing_id_, this); + registry_->UnregisterLayerTreeFrameSink(this); client_->SetTreeActivationCallback(base::RepeatingClosure()); root_support_.reset(); child_support_.reset(); @@ -279,13 +278,13 @@ void SynchronousLayerTreeFrameSink::DetachFromClient() { cc::LayerTreeFrameSink::DetachFromClient(); } -void SynchronousLayerTreeFrameSink::SetLocalSurfaceId( +void SynchronousLayerTreeFrameSinkImpl::SetLocalSurfaceId( const viz::LocalSurfaceId& local_surface_id) { DCHECK(CalledOnValidThread()); local_surface_id_ = local_surface_id; } -void SynchronousLayerTreeFrameSink::SubmitCompositorFrame( +void SynchronousLayerTreeFrameSinkImpl::SubmitCompositorFrame( viz::CompositorFrame frame, bool hit_test_data_changed, bool show_hit_test_borders) { @@ -419,14 +418,14 @@ void SynchronousLayerTreeFrameSink::SubmitCompositorFrame( did_submit_frame_ = true; } -void SynchronousLayerTreeFrameSink::DidNotProduceFrame( +void SynchronousLayerTreeFrameSinkImpl::DidNotProduceFrame( const viz::BeginFrameAck& ack) { // We do not call CompositorFrameSink::DidNotProduceFrame here because // submission of frame depends on DemandDraw calls. DidNotProduceFrame will be // called there or during OnBeginFrame as fallback. } -void SynchronousLayerTreeFrameSink::DidAllocateSharedBitmap( +void SynchronousLayerTreeFrameSinkImpl::DidAllocateSharedBitmap( base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { // Webview does not use software compositing (other than resourceless draws, @@ -434,20 +433,20 @@ void SynchronousLayerTreeFrameSink::DidAllocateSharedBitmap( NOTREACHED(); } -void SynchronousLayerTreeFrameSink::DidDeleteSharedBitmap( +void SynchronousLayerTreeFrameSinkImpl::DidDeleteSharedBitmap( const viz::SharedBitmapId& id) { // Webview does not use software compositing (other than resourceless draws, // but this is called for software /resources/). NOTREACHED(); } -void SynchronousLayerTreeFrameSink::Invalidate(bool needs_draw) { +void SynchronousLayerTreeFrameSinkImpl::Invalidate(bool needs_draw) { DCHECK(CalledOnValidThread()); if (sync_client_) sync_client_->Invalidate(needs_draw); } -void SynchronousLayerTreeFrameSink::DemandDrawHw( +void SynchronousLayerTreeFrameSinkImpl::DemandDrawHw( const gfx::Size& viewport_size, const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Transform& transform_for_tile_priority) { @@ -460,7 +459,7 @@ void SynchronousLayerTreeFrameSink::DemandDrawHw( InvokeComposite(gfx::Transform(), gfx::Rect(viewport_size)); } -void SynchronousLayerTreeFrameSink::DemandDrawSw(SkCanvas* canvas) { +void SynchronousLayerTreeFrameSinkImpl::DemandDrawSw(SkCanvas* canvas) { DCHECK(CalledOnValidThread()); DCHECK(canvas); DCHECK(!current_sw_canvas_); @@ -481,12 +480,12 @@ void SynchronousLayerTreeFrameSink::DemandDrawSw(SkCanvas* canvas) { InvokeComposite(transform, viewport); } -void SynchronousLayerTreeFrameSink::WillSkipDraw() { +void SynchronousLayerTreeFrameSinkImpl::WillSkipDraw() { client_->OnDraw(gfx::Transform(), gfx::Rect(), in_software_draw_, true /*skip_draw*/); } -void SynchronousLayerTreeFrameSink::InvokeComposite( +void SynchronousLayerTreeFrameSinkImpl::InvokeComposite( const gfx::Transform& transform, const gfx::Rect& viewport) { did_submit_frame_ = false; @@ -508,7 +507,7 @@ void SynchronousLayerTreeFrameSink::InvokeComposite( } } -void SynchronousLayerTreeFrameSink::ReclaimResources( +void SynchronousLayerTreeFrameSinkImpl::ReclaimResources( uint32_t layer_tree_frame_sink_id, const std::vector<viz::ReturnedResource>& resources) { // Ignore message if it's a stale one coming from a different output surface @@ -518,7 +517,7 @@ void SynchronousLayerTreeFrameSink::ReclaimResources( client_->ReclaimResources(resources); } -void SynchronousLayerTreeFrameSink::SetMemoryPolicy(size_t bytes_limit) { +void SynchronousLayerTreeFrameSinkImpl::SetMemoryPolicy(size_t bytes_limit) { DCHECK(CalledOnValidThread()); bool became_zero = memory_policy_.bytes_limit_when_visible && !bytes_limit; bool became_non_zero = @@ -540,14 +539,14 @@ void SynchronousLayerTreeFrameSink::SetMemoryPolicy(size_t bytes_limit) { } } -void SynchronousLayerTreeFrameSink::DidActivatePendingTree() { +void SynchronousLayerTreeFrameSinkImpl::DidActivatePendingTree() { DCHECK(CalledOnValidThread()); if (sync_client_) sync_client_->DidActivatePendingTree(); DeliverMessages(); } -void SynchronousLayerTreeFrameSink::DeliverMessages() { +void SynchronousLayerTreeFrameSinkImpl::DeliverMessages() { std::vector<std::unique_ptr<IPC::Message>> messages; std::unique_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope = frame_swap_message_queue_->AcquireSendMessageScope(); @@ -557,16 +556,16 @@ void SynchronousLayerTreeFrameSink::DeliverMessages() { } } -bool SynchronousLayerTreeFrameSink::Send(IPC::Message* message) { +bool SynchronousLayerTreeFrameSinkImpl::Send(IPC::Message* message) { DCHECK(CalledOnValidThread()); return sender_->Send(message); } -bool SynchronousLayerTreeFrameSink::CalledOnValidThread() const { +bool SynchronousLayerTreeFrameSinkImpl::CalledOnValidThread() const { return thread_checker_.CalledOnValidThread(); } -void SynchronousLayerTreeFrameSink::DidReceiveCompositorFrameAck( +void SynchronousLayerTreeFrameSinkImpl::DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) { DCHECK(CalledOnValidThread()); DCHECK(viz_frame_submission_enabled_); @@ -576,7 +575,7 @@ void SynchronousLayerTreeFrameSink::DidReceiveCompositorFrameAck( // (or not happen at all) for WebView. } -void SynchronousLayerTreeFrameSink::OnBeginFrame( +void SynchronousLayerTreeFrameSinkImpl::OnBeginFrame( const viz::BeginFrameArgs& args, const viz::FrameTimingDetailsMap& timing_details) { DCHECK(viz_frame_submission_enabled_); @@ -592,18 +591,18 @@ void SynchronousLayerTreeFrameSink::OnBeginFrame( } } -void SynchronousLayerTreeFrameSink::ReclaimResources( +void SynchronousLayerTreeFrameSinkImpl::ReclaimResources( const std::vector<viz::ReturnedResource>& resources) { DCHECK(CalledOnValidThread()); DCHECK(viz_frame_submission_enabled_); client_->ReclaimResources(resources); } -void SynchronousLayerTreeFrameSink::OnBeginFramePausedChanged(bool paused) { +void SynchronousLayerTreeFrameSinkImpl::OnBeginFramePausedChanged(bool paused) { DCHECK(viz_frame_submission_enabled_); } -void SynchronousLayerTreeFrameSink::OnNeedsBeginFrames( +void SynchronousLayerTreeFrameSinkImpl::OnNeedsBeginFrames( bool needs_begin_frames) { needs_begin_frames_ = needs_begin_frames; if (sync_client_) { @@ -611,7 +610,7 @@ void SynchronousLayerTreeFrameSink::OnNeedsBeginFrames( } } -void SynchronousLayerTreeFrameSink::DidPresentCompositorFrame( +void SynchronousLayerTreeFrameSinkImpl::DidPresentCompositorFrame( const viz::FrameTimingDetailsMap& timing_details) { DCHECK(!viz_frame_submission_enabled_ || timing_details.empty()); @@ -621,13 +620,13 @@ void SynchronousLayerTreeFrameSink::DidPresentCompositorFrame( client_->DidPresentCompositorFrame(pair.first, pair.second); } -void SynchronousLayerTreeFrameSink::BeginFrame( +void SynchronousLayerTreeFrameSinkImpl::BeginFrame( const viz::BeginFrameArgs& args) { if (external_begin_frame_source_) external_begin_frame_source_->OnBeginFrame(args); } -void SynchronousLayerTreeFrameSink::SetBeginFrameSourcePaused(bool paused) { +void SynchronousLayerTreeFrameSinkImpl::SetBeginFrameSourcePaused(bool paused) { if (external_begin_frame_source_) external_begin_frame_source_->OnSetBeginFrameSourcePaused(paused); } diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink_impl.h index 8e2a2c39220..9a2aa507669 100644 --- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink_impl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_ANDROID_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ -#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ +#ifndef CONTENT_RENDERER_ANDROID_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_IMPL_H_ +#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_IMPL_H_ #include <stddef.h> @@ -26,6 +26,7 @@ #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/service/display/display_client.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" +#include "content/renderer/input/synchronous_layer_tree_frame_sink.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -54,21 +55,6 @@ namespace content { class FrameSwapMessageQueue; class SynchronousCompositorRegistry; -class SynchronousLayerTreeFrameSinkClient { - public: - virtual void DidActivatePendingTree() = 0; - virtual void Invalidate(bool needs_draw) = 0; - virtual void SubmitCompositorFrame( - uint32_t layer_tree_frame_sink_id, - base::Optional<viz::CompositorFrame> frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list) = 0; - virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0; - virtual void SinkDestroyed() = 0; - - protected: - virtual ~SynchronousLayerTreeFrameSinkClient() {} -}; - // Specialization of the output surface that adapts it to implement the // content::SynchronousCompositor public API. This class effects an "inversion // of control" - enabling drawing to be orchestrated by the embedding @@ -77,18 +63,17 @@ class SynchronousLayerTreeFrameSinkClient { // |delegate_|) which represent the consumers of the two roles in plays. // This class can be created only on the main thread, but then becomes pinned // to a fixed thread when BindToClient is called. -class SynchronousLayerTreeFrameSink - : public cc::LayerTreeFrameSink, +class SynchronousLayerTreeFrameSinkImpl + : public SynchronousLayerTreeFrameSink, public viz::mojom::CompositorFrameSinkClient, public viz::ExternalBeginFrameSourceClient { public: - SynchronousLayerTreeFrameSink( + SynchronousLayerTreeFrameSinkImpl( scoped_refptr<viz::ContextProvider> context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, IPC::Sender* sender, - int routing_id, uint32_t layer_tree_frame_sink_id, std::unique_ptr<viz::BeginFrameSource> begin_frame_source, SynchronousCompositorRegistry* registry, @@ -97,9 +82,7 @@ class SynchronousLayerTreeFrameSink compositor_frame_sink_remote, mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> client_receiver); - ~SynchronousLayerTreeFrameSink() override; - - void SetSyncClient(SynchronousLayerTreeFrameSinkClient* compositor); + ~SynchronousLayerTreeFrameSinkImpl() override; // cc::LayerTreeFrameSink implementation. bool BindToClient(cc::LayerTreeFrameSinkClient* sink_client) override; @@ -114,13 +97,6 @@ class SynchronousLayerTreeFrameSink void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; void Invalidate(bool needs_draw) override; - // Partial SynchronousCompositor API implementation. - void DemandDrawHw(const gfx::Size& viewport_size, - const gfx::Rect& viewport_rect_for_tile_priority, - const gfx::Transform& transform_for_tile_priority); - void DemandDrawSw(SkCanvas* canvas); - void WillSkipDraw(); - // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; @@ -133,13 +109,21 @@ class SynchronousLayerTreeFrameSink // viz::ExternalBeginFrameSourceClient overrides. void OnNeedsBeginFrames(bool needs_begin_frames) override; + // SynchronousLayerTreeFrameSink overrides. + void SetSyncClient(SynchronousLayerTreeFrameSinkClient* compositor) override; void DidPresentCompositorFrame( - const viz::FrameTimingDetailsMap& timing_details); - void BeginFrame(const viz::BeginFrameArgs& args); - void SetBeginFrameSourcePaused(bool paused); - void SetMemoryPolicy(size_t bytes_limit); - void ReclaimResources(uint32_t layer_tree_frame_sink_id, - const std::vector<viz::ReturnedResource>& resources); + const viz::FrameTimingDetailsMap& timing_details) override; + void BeginFrame(const viz::BeginFrameArgs& args) override; + void SetBeginFrameSourcePaused(bool paused) override; + void SetMemoryPolicy(size_t bytes_limit) override; + void ReclaimResources( + uint32_t layer_tree_frame_sink_id, + const std::vector<viz::ReturnedResource>& resources) override; + void DemandDrawHw(const gfx::Size& viewport_size, + const gfx::Rect& viewport_rect_for_tile_priority, + const gfx::Transform& transform_for_tile_priority) override; + void DemandDrawSw(SkCanvas* canvas) override; + void WillSkipDraw() override; private: class SoftwareOutputSurface; @@ -151,11 +135,9 @@ class SynchronousLayerTreeFrameSink void DeliverMessages(); bool CalledOnValidThread() const; - - const int routing_id_; const uint32_t layer_tree_frame_sink_id_; - SynchronousCompositorRegistry* const registry_; // Not owned. - IPC::Sender* const sender_; // Not owned. + SynchronousCompositorRegistry* const registry_; // Not owned. + IPC::Sender* const sender_; // Not owned. // Not owned. SynchronousLayerTreeFrameSinkClient* sync_client_ = nullptr; @@ -165,7 +147,7 @@ class SynchronousLayerTreeFrameSink // process so there is no reason for it to use a SharedBitmapManager. viz::ServerSharedBitmapManager shared_bitmap_manager_; - // Only valid (non-NULL) during a DemandDrawSw() call. + // Only valid (non-null) during a DemandDrawSw() call. SkCanvas* current_sw_canvas_ = nullptr; cc::ManagedMemoryPolicy memory_policy_; @@ -228,9 +210,9 @@ class SynchronousLayerTreeFrameSink bool begin_frames_paused_ = false; bool needs_begin_frames_ = false; - DISALLOW_COPY_AND_ASSIGN(SynchronousLayerTreeFrameSink); + DISALLOW_COPY_AND_ASSIGN(SynchronousLayerTreeFrameSinkImpl); }; } // namespace content -#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ +#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_IMPL_H_ diff --git a/chromium/content/renderer/browser_exposed_renderer_interfaces.cc b/chromium/content/renderer/browser_exposed_renderer_interfaces.cc index ac78340e92b..8267a81d5fe 100644 --- a/chromium/content/renderer/browser_exposed_renderer_interfaces.cc +++ b/chromium/content/renderer/browser_exposed_renderer_interfaces.cc @@ -17,11 +17,13 @@ #include "base/task/thread_pool.h" #include "base/task_runner.h" #include "base/time/time.h" +#include "build/build_config.h" #include "content/common/frame.mojom.h" #include "content/public/common/content_client.h" #include "content/public/common/resource_usage_reporter.mojom.h" #include "content/public/common/resource_usage_reporter_type_converters.h" #include "content/public/renderer/content_renderer_client.h" +#include "content/renderer/loader/resource_dispatcher.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h" @@ -31,6 +33,10 @@ #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "v8/include/v8.h" +#if !defined(OS_ANDROID) +#include "content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h" +#endif + namespace content { namespace { @@ -181,6 +187,20 @@ void CreateFrameFactory(mojo::PendingReceiver<mojom::FrameFactory> receiver) { std::move(receiver)); } +void CreateEmbeddedWorker( + scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner, + base::WeakPtr<RenderThreadImpl> render_thread, + mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> + receiver) { + initiator_task_runner->PostTask( + FROM_HERE, + base::BindOnce( + &EmbeddedWorkerInstanceClientImpl::CreateForRequest, + initiator_task_runner, + render_thread->resource_dispatcher()->cors_exempt_header_list(), + std::move(receiver))); +} + } // namespace void ExposeRendererInterfacesToBrowser( @@ -197,14 +217,22 @@ void ExposeRendererInterfacesToBrowser( base::ThreadPool::CreateSingleThreadTaskRunner( {base::MayBlock(), base::TaskPriority::USER_BLOCKING, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); - binders->Add( - base::BindRepeating(&EmbeddedWorkerInstanceClientImpl::CreateForRequest, - task_runner_for_service_worker_startup), - task_runner_for_service_worker_startup); + binders->Add(base::BindRepeating(&CreateEmbeddedWorker, + task_runner_for_service_worker_startup, + render_thread), + base::ThreadTaskRunnerHandle::Get()); binders->Add(base::BindRepeating(&CreateFrameFactory), base::ThreadTaskRunnerHandle::Get()); +#if !defined(OS_ANDROID) + // Currently nothing on Android samples V8PerFrameMemory, so only initialize + // the reporter on desktop to save memory. + binders->Add(base::BindRepeating( + &performance_manager::V8PerFrameMemoryReporterImpl::Create), + base::SequencedTaskRunnerHandle::Get()); +#endif + GetContentClient()->renderer()->ExposeInterfacesToBrowser(binders); } diff --git a/chromium/content/renderer/browser_render_view_browsertest.cc b/chromium/content/renderer/browser_render_view_browsertest.cc index 7431feb78d8..6c85d3da447 100644 --- a/chromium/content/renderer/browser_render_view_browsertest.cc +++ b/chromium/content/renderer/browser_render_view_browsertest.cc @@ -34,7 +34,6 @@ #include "content/shell/renderer/shell_content_renderer_client.h" #include "net/base/net_errors.h" #include "net/disk_cache/disk_cache.h" -#include "net/http/failing_http_transaction_factory.h" #include "net/http/http_cache.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" diff --git a/chromium/content/renderer/discardable_memory_utils.h b/chromium/content/renderer/discardable_memory_utils.h index 42b6c3cbbf2..ff143ec4e98 100644 --- a/chromium/content/renderer/discardable_memory_utils.h +++ b/chromium/content/renderer/discardable_memory_utils.h @@ -10,7 +10,6 @@ #include <memory> #include "base/feature_list.h" -#include "base/logging.h" #include "base/macros.h" #include "base/memory/discardable_memory.h" #include "base/memory/discardable_memory_allocator.h" @@ -20,7 +19,6 @@ #include "build/build_config.h" #include "components/discardable_memory/client/client_discardable_shared_memory_manager.h" #include "content/common/content_export.h" -#include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc index 63da2c9fff1..c5c341acf5d 100644 --- a/chromium/content/renderer/dom_serializer_browsertest.cc +++ b/chromium/content/renderer/dom_serializer_browsertest.cc @@ -25,7 +25,6 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/frame_load_waiter.h" #include "content/public/test/test_utils.h" -#include "content/renderer/savable_resources.h" #include "content/shell/browser/shell.h" #include "net/base/filename_util.h" #include "net/url_request/url_request_context.h" @@ -42,6 +41,7 @@ #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_meta_element.h" #include "third_party/blink/public/web/web_node.h" +#include "third_party/blink/public/web/web_savable_resources_test_support.h" #include "third_party/blink/public/web/web_view.h" using blink::WebData; @@ -493,7 +493,8 @@ class MAYBE_DomSerializerTests : public ContentBrowserTest, original_base_tag_count++; } else { // Get link. - WebString value = GetSubResourceLinkFromElement(element); + WebString value = + blink::GetSubResourceLinkFromElementForTesting(element); if (value.IsNull() && element.HasHTMLTagName("a")) { value = element.GetAttribute("href"); if (value.IsEmpty()) @@ -539,7 +540,8 @@ class MAYBE_DomSerializerTests : public ContentBrowserTest, new_base_tag_count++; } else { // Get link. - WebString value = GetSubResourceLinkFromElement(element); + WebString value = + blink::GetSubResourceLinkFromElementForTesting(element); if (value.IsNull() && element.HasHTMLTagName("a")) { value = element.GetAttribute("href"); if (value.IsEmpty()) @@ -616,8 +618,8 @@ class MAYBE_DomSerializerTests : public ContentBrowserTest, WebDocument doc = web_frame->GetDocument(); WebNode lastNodeInBody = doc.Body().LastChild(); ASSERT_TRUE(lastNodeInBody.IsElementNode()); - WebString uri = - GetSubResourceLinkFromElement(lastNodeInBody.To<WebElement>()); + WebString uri = blink::GetSubResourceLinkFromElementForTesting( + lastNodeInBody.To<WebElement>()); EXPECT_TRUE(uri.IsNull()); } diff --git a/chromium/content/renderer/drop_data_builder.cc b/chromium/content/renderer/drop_data_builder.cc index ad2fa8df394..f844da3b2cb 100644 --- a/chromium/content/renderer/drop_data_builder.cc +++ b/chromium/content/renderer/drop_data_builder.cc @@ -32,7 +32,7 @@ DropData DropDataBuilder::Build(const WebDragData& drag_data) { case WebDragData::Item::kStorageTypeString: { base::string16 str_type(item.string_type.Utf16()); if (base::EqualsASCII(str_type, ui::kMimeTypeText)) { - result.text = WebString::ToNullableString16(item.string_data); + result.text = WebString::ToOptionalString16(item.string_data); break; } if (base::EqualsASCII(str_type, ui::kMimeTypeURIList)) { @@ -45,7 +45,7 @@ DropData DropDataBuilder::Build(const WebDragData& drag_data) { break; } if (base::EqualsASCII(str_type, ui::kMimeTypeHTML)) { - result.html = WebString::ToNullableString16(item.string_data); + result.html = WebString::ToOptionalString16(item.string_data); result.html_base_url = item.base_url; break; } diff --git a/chromium/content/renderer/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu_benchmarking_extension.cc index 45766087a71..de566597dc9 100644 --- a/chromium/content/renderer/gpu_benchmarking_extension.cc +++ b/chromium/content/renderer/gpu_benchmarking_extension.cc @@ -1335,6 +1335,9 @@ bool GpuBenchmarking::AddSwapCompletionEventListener(gin::Arguments* args) { base::NullCallback(), base::BindOnce(&OnSwapCompletedHelper, base::RetainedRef(callback_and_context))); + // Request a begin frame explicitly, as the test-api expects a 'swap' to + // happen for the above queued swap promise even if there is no actual update. + context.layer_tree_host()->SetNeedsAnimateIfNotInsideMainFrame(); return true; } diff --git a/chromium/content/renderer/input/frame_input_handler_impl.cc b/chromium/content/renderer/input/frame_input_handler_impl.cc index 3f710c7066e..977ebdf25c9 100644 --- a/chromium/content/renderer/input/frame_input_handler_impl.cc +++ b/chromium/content/renderer/input/frame_input_handler_impl.cc @@ -8,12 +8,10 @@ #include "base/bind.h" #include "base/check.h" -#include "content/common/input/ime_text_span_conversions.h" -#include "content/common/input/input_handler.mojom.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_manager.h" +#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_view_impl.h" #include "content/renderer/render_widget.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -23,40 +21,15 @@ namespace content { FrameInputHandlerImpl::FrameInputHandlerImpl( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver) - : render_frame_(render_frame), - input_event_queue_( - render_frame->GetLocalRootRenderWidget()->GetInputEventQueue()), - main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) { - weak_this_ = weak_ptr_factory_.GetWeakPtr(); - // If we have created an input event queue move the mojo request over to the - // compositor thread. - if (RenderThreadImpl::current() && - RenderThreadImpl::current()->compositor_task_runner() && - input_event_queue_) { - // Mojo channel bound on compositor thread. - RenderThreadImpl::current()->compositor_task_runner()->PostTask( - FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::BindNow, - base::Unretained(this), std::move(receiver))); - } else { - // Mojo channel bound on main thread. - BindNow(std::move(receiver)); - } -} + base::WeakPtr<RenderWidget> widget, + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + scoped_refptr<MainThreadEventQueue> input_event_queue) + : widget_(widget), + input_event_queue_(input_event_queue), + main_thread_task_runner_(main_thread_task_runner) {} FrameInputHandlerImpl::~FrameInputHandlerImpl() {} -// static -void FrameInputHandlerImpl::CreateMojoService( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver) { - DCHECK(render_frame); - - // Owns itself. Will be deleted when message pipe is destroyed. - new FrameInputHandlerImpl(render_frame, std::move(receiver)); -} - void FrameInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) { if (input_event_queue_) { input_event_queue_->QueueClosure(std::move(closure)); @@ -69,269 +42,316 @@ void FrameInputHandlerImpl::SetCompositionFromExistingText( int32_t start, int32_t end, const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::SetCompositionFromExistingText, - weak_this_, start, end, ui_ime_text_spans)); - return; - } - - if (!render_frame_) - return; + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end, + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { + if (!widget) + return; - ImeEventGuard guard(render_frame_->GetLocalRootRenderWidget()->AsWeakPtr()); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + ImeEventGuard guard(widget); - render_frame_->GetWebFrame()->SetCompositionFromExistingText( - start, end, ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans)); + focused_frame->SetCompositionFromExistingText(start, end, + ui_ime_text_spans); + }, + widget_, start, end, ui_ime_text_spans)); } void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before, int32_t after) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::ExtendSelectionAndDelete, - weak_this_, before, after)); - return; - } - if (!render_frame_) - return; - render_frame_->GetWebFrame()->ExtendSelectionAndDelete(before, after); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) { + if (!widget) + return; + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->ExtendSelectionAndDelete(before, after); + }, + widget_, before, after)); } void FrameInputHandlerImpl::DeleteSurroundingText(int32_t before, int32_t after) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::DeleteSurroundingText, - weak_this_, before, after)); - return; - } - if (!render_frame_) - return; - render_frame_->GetWebFrame()->DeleteSurroundingText(before, after); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) { + if (!widget) + return; + + if (!widget) + return; + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->DeleteSurroundingText(before, after); + }, + widget_, before, after)); } void FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints(int32_t before, int32_t after) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints, weak_this_, - before, after)); - return; - } - if (!render_frame_) - return; - render_frame_->GetWebFrame()->DeleteSurroundingTextInCodePoints(before, - after); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->DeleteSurroundingTextInCodePoints(before, after); + }, + widget_, before, after)); } void FrameInputHandlerImpl::SetEditableSelectionOffsets(int32_t start, int32_t end) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::SetEditableSelectionOffsets, - weak_this_, start, end)); - return; - } - if (!render_frame_) - return; - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->SetEditableSelectionOffsets(start, end); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->SetEditableSelectionOffsets(start, end); + }, + widget_, start, end)); } void FrameInputHandlerImpl::ExecuteEditCommand( const std::string& command, const base::Optional<base::string16>& value) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ExecuteEditCommand, - weak_this_, command, value)); - return; - } - if (!render_frame_) - return; - if (value) { - render_frame_->GetWebFrame()->ExecuteCommand( - blink::WebString::FromUTF8(command), - blink::WebString::FromUTF16(value.value())); - return; - } + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const std::string& command, + const base::Optional<base::string16>& value) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + if (value) { + focused_frame->ExecuteCommand( + blink::WebString::FromUTF8(command), + blink::WebString::FromUTF16(value.value())); + return; + } - render_frame_->GetWebFrame()->ExecuteCommand( - blink::WebString::FromUTF8(command)); + focused_frame->ExecuteCommand(blink::WebString::FromUTF8(command)); + }, + widget_, command, value)); } void FrameInputHandlerImpl::Undo() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Undo", UpdateState::kNone)); + widget_, "Undo", UpdateState::kNone)); } void FrameInputHandlerImpl::Redo() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Redo", UpdateState::kNone)); + widget_, "Redo", UpdateState::kNone)); } void FrameInputHandlerImpl::Cut() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Cut", UpdateState::kIsSelectingRange)); + widget_, "Cut", UpdateState::kIsSelectingRange)); } void FrameInputHandlerImpl::Copy() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Copy", UpdateState::kIsSelectingRange)); + widget_, "Copy", UpdateState::kIsSelectingRange)); } void FrameInputHandlerImpl::CopyToFindPboard() { #if defined(OS_MACOSX) - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::CopyToFindPboard, weak_this_)); - return; - } - if (!render_frame_) - return; - render_frame_->OnCopyToFindPboard(); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(focused_frame); + + if (!render_frame) + return; + + render_frame->OnCopyToFindPboard(); + }, + widget_)); #endif } void FrameInputHandlerImpl::Paste() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Paste", UpdateState::kIsPasting)); + widget_, "Paste", UpdateState::kIsPasting)); } void FrameInputHandlerImpl::PasteAndMatchStyle() { - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::ExecuteCommandOnMainThread, weak_this_, - "PasteAndMatchStyle", UpdateState::kIsPasting)); + RunOnMainThread( + base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, + widget_, "PasteAndMatchStyle", UpdateState::kIsPasting)); } void FrameInputHandlerImpl::Replace(const base::string16& word) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::Replace, weak_this_, word)); - return; - } - if (!render_frame_) - return; - blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); - if (!frame->HasSelection()) - frame->SelectWordAroundCaret(); - frame->ReplaceSelection(blink::WebString::FromUTF16(word)); - render_frame_->SyncSelectionIfRequired(); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const base::string16& word) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(focused_frame); + + if (!render_frame) + return; + + if (!focused_frame->HasSelection()) + focused_frame->SelectWordAroundCaret(); + focused_frame->ReplaceSelection(blink::WebString::FromUTF16(word)); + render_frame->SyncSelectionIfRequired(); + }, + widget_, word)); } void FrameInputHandlerImpl::ReplaceMisspelling(const base::string16& word) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ReplaceMisspelling, - weak_this_, word)); - return; - } - if (!render_frame_) - return; - blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); - if (!frame->HasSelection()) - return; - frame->ReplaceMisspelledRange(blink::WebString::FromUTF16(word)); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const base::string16& word) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + if (!focused_frame->HasSelection()) + return; + focused_frame->ReplaceMisspelledRange( + blink::WebString::FromUTF16(word)); + }, + widget_, word)); } void FrameInputHandlerImpl::Delete() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Delete", UpdateState::kNone)); + widget_, "Delete", UpdateState::kNone)); } void FrameInputHandlerImpl::SelectAll() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "SelectAll", UpdateState::kIsSelectingRange)); + widget_, "SelectAll", UpdateState::kIsSelectingRange)); } void FrameInputHandlerImpl::CollapseSelection() { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::CollapseSelection, weak_this_)); - return; - } - - if (!render_frame_) - return; - const blink::WebRange& range = render_frame_->GetWebFrame() - ->GetInputMethodController() - ->GetSelectionOffsets(); - if (range.IsNull()) - return; - - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->SelectRange( - blink::WebRange(range.EndOffset(), 0), - blink::WebLocalFrame::kHideSelectionHandle, - blink::mojom::SelectionMenuBehavior::kHide); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + const blink::WebRange& range = + focused_frame->GetInputMethodController()->GetSelectionOffsets(); + if (range.IsNull()) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0), + blink::WebLocalFrame::kHideSelectionHandle, + blink::mojom::SelectionMenuBehavior::kHide); + }, + widget_)); } void FrameInputHandlerImpl::SelectRange(const gfx::Point& base, const gfx::Point& extent) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { // TODO(dtapuska): This event should be coalesced. Chrome IPC uses // one outstanding event and an ACK to handle coalescing on the browser // side. We should be able to clobber them in the main thread event queue. - RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::SelectRange, - weak_this_, base, extent)); - return; - } + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Point& base, + const gfx::Point& extent) { + if (!widget) + return; - if (!render_frame_) - return; - RenderWidget* window_widget = render_frame_->GetLocalRootRenderWidget(); - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->SelectRange( - window_widget->ConvertWindowPointToViewport(base), - window_widget->ConvertWindowPointToViewport(extent)); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->SelectRange( + widget->ConvertWindowPointToViewport(base), + widget->ConvertWindowPointToViewport(extent)); + }, + widget_, base, extent)); } #if defined(OS_ANDROID) void FrameInputHandlerImpl::SelectWordAroundCaret( SelectWordAroundCaretCallback callback) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::SelectWordAroundCaret, - weak_this_, std::move(callback))); - return; - } - - bool did_select = false; - int start_adjust = 0; - int end_adjust = 0; - if (render_frame_) { - blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); - blink::WebRange initial_range = frame->SelectionRange(); - render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(true); - if (!initial_range.IsNull()) - did_select = frame->SelectWordAroundCaret(); - if (did_select) { - blink::WebRange adjusted_range = frame->SelectionRange(); - DCHECK(!adjusted_range.IsNull()); - start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset(); - end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset(); - } - render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(false); - } - // If the mojom channel is registered with compositor thread, we have to run // the callback on compositor thread. Otherwise run it on main thread. Mojom // requires the callback runs on the same thread. - if (RenderThreadImpl::current() && - RenderThreadImpl::current()->compositor_task_runner() && - input_event_queue_) { - RenderThreadImpl::current()->compositor_task_runner()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), did_select, start_adjust, - end_adjust)); - } else { - std::move(callback).Run(did_select, start_adjust, end_adjust); + if (!main_thread_task_runner_->BelongsToCurrentThread()) { + callback = base::BindOnce( + [](scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, + SelectWordAroundCaretCallback callback, bool did_select, + int32_t start_adjust, int32_t end_adjust) { + compositor_task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), did_select, + start_adjust, end_adjust)); + }, + base::ThreadTaskRunnerHandle::Get(), std::move(callback)); } + + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, + SelectWordAroundCaretCallback callback) { + if (!widget) { + std::move(callback).Run(false, 0, 0); + return; + } + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) { + std::move(callback).Run(false, 0, 0); + return; + } + + bool did_select = false; + int start_adjust = 0; + int end_adjust = 0; + blink::WebRange initial_range = focused_frame->SelectionRange(); + widget->SetHandlingInputEvent(true); + if (!initial_range.IsNull()) + did_select = focused_frame->SelectWordAroundCaret(); + if (did_select) { + blink::WebRange adjusted_range = focused_frame->SelectionRange(); + DCHECK(!adjusted_range.IsNull()); + start_adjust = + adjusted_range.StartOffset() - initial_range.StartOffset(); + end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset(); + } + widget->SetHandlingInputEvent(false); + std::move(callback).Run(did_select, start_adjust, end_adjust); + }, + widget_, std::move(callback))); } #endif // defined(OS_ANDROID) @@ -339,147 +359,126 @@ void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset( int32_t start, int32_t end, blink::mojom::SelectionMenuBehavior selection_menu_behavior) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::AdjustSelectionByCharacterOffset, - weak_this_, start, end, selection_menu_behavior)); - return; - } - - if (!render_frame_) - return; - blink::WebRange range = render_frame_->GetWebFrame() - ->GetInputMethodController() - ->GetSelectionOffsets(); - if (range.IsNull()) - return; - - // Sanity checks to disallow empty and out of range selections. - if (start - end > range.length() || range.StartOffset() + start < 0) - return; - - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - // A negative adjust amount moves the selection towards the beginning of - // the document, a positive amount moves the selection towards the end of - // the document. - render_frame_->GetWebFrame()->SelectRange( - blink::WebRange(range.StartOffset() + start, - range.length() + end - start), - blink::WebLocalFrame::kPreserveHandleVisibility, selection_menu_behavior); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end, + blink::mojom::SelectionMenuBehavior selection_menu_behavior) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + blink::WebRange range = + focused_frame->GetInputMethodController()->GetSelectionOffsets(); + if (range.IsNull()) + return; + + // Sanity checks to disallow empty and out of range selections. + if (start - end > range.length() || range.StartOffset() + start < 0) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + // A negative adjust amount moves the selection towards the beginning of + // the document, a positive amount moves the selection towards the end + // of the document. + focused_frame->SelectRange( + blink::WebRange(range.StartOffset() + start, + range.length() + end - start), + blink::WebLocalFrame::kPreserveHandleVisibility, + selection_menu_behavior); + }, + widget_, start, end, selection_menu_behavior)); } void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - // TODO(dtapuska): This event should be coalesced. Chrome IPC uses - // one outstanding event and an ACK to handle coalescing on the browser - // side. We should be able to clobber them in the main thread event queue. - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::MoveRangeSelectionExtent, weak_this_, extent)); - return; - } + // TODO(dtapuska): This event should be coalesced. Chrome IPC uses + // one outstanding event and an ACK to handle coalescing on the browser + // side. We should be able to clobber them in the main thread event queue. + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Point& extent) { + if (!widget) + return; - if (!render_frame_) - return; - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->MoveRangeSelectionExtent( - render_frame_->GetLocalRootRenderWidget()->ConvertWindowPointToViewport( - extent)); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->MoveRangeSelectionExtent( + widget->ConvertWindowPointToViewport(extent)); + }, + widget_, extent)); } void FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect( const gfx::Rect& rect) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect, weak_this_, - rect)); - return; - } + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Rect& rect) { + if (!widget) + return; - if (!render_frame_) - return; + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; - // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport - // on OOPIFs. Since we are starting a new scroll operation now, call - // DidChangeVisibleViewport to ensure that we don't assume the element - // is already in view and ignore the scroll. - render_frame_->ResetHasScrolledFocusedEditableIntoView(); - render_frame_->ScrollFocusedEditableElementIntoRect(rect); -} + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(focused_frame); -void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::MoveCaret, weak_this_, point)); - return; - } + if (!render_frame) + return; - if (!render_frame_) - return; - - render_frame_->GetWebFrame()->MoveCaretSelection( - render_frame_->GetLocalRootRenderWidget()->ConvertWindowPointToViewport( - point)); + // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport + // on OOPIFs. Since we are starting a new scroll operation now, call + // DidChangeVisibleViewport to ensure that we don't assume the element + // is already in view and ignore the scroll. + render_frame->ResetHasScrolledFocusedEditableIntoView(); + render_frame->ScrollFocusedEditableElementIntoRect(rect); + }, + widget_, rect)); } -void FrameInputHandlerImpl::GetWidgetInputHandler( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - main_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&FrameInputHandlerImpl::GetWidgetInputHandler, - weak_this_, std::move(receiver), std::move(host))); - return; - } - if (!render_frame_) - return; - render_frame_->GetLocalRootRenderWidget() - ->widget_input_handler_manager() - ->AddAssociatedInterface(std::move(receiver), std::move(host)); +void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) { + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Point& point) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->MoveCaretSelection( + widget->ConvertWindowPointToViewport(point)); + }, + widget_, point)); } void FrameInputHandlerImpl::ExecuteCommandOnMainThread( + base::WeakPtr<RenderWidget> widget, const std::string& command, UpdateState update_state) { - if (!render_frame_) + if (!widget) return; - HandlingState handling_state(render_frame_, update_state); - render_frame_->GetWebFrame()->ExecuteCommand( - blink::WebString::FromUTF8(command)); -} - -void FrameInputHandlerImpl::Release() { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - // Close the receiver on the compositor thread first before telling the main - // thread to delete this object. - receiver_.reset(); - main_thread_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::Release, weak_this_)); + HandlingState handling_state(widget, update_state); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) return; - } - delete this; -} - -void FrameInputHandlerImpl::BindNow( - mojo::PendingReceiver<mojom::FrameInputHandler> receiver) { - receiver_.Bind(std::move(receiver)); - receiver_.set_disconnect_handler( - base::BindOnce(&FrameInputHandlerImpl::Release, base::Unretained(this))); + focused_frame->ExecuteCommand(blink::WebString::FromUTF8(command)); } FrameInputHandlerImpl::HandlingState::HandlingState( - const base::WeakPtr<RenderFrameImpl>& render_frame, + const base::WeakPtr<RenderWidget>& render_widget, UpdateState state) - : render_frame_(render_frame), - original_select_range_value_(render_frame->handling_select_range()), - original_pasting_value_(render_frame->IsPasting()) { + : render_widget_(render_widget), + original_select_range_value_(render_widget->handling_select_range()), + original_pasting_value_(render_widget->is_pasting()) { switch (state) { case UpdateState::kIsPasting: - render_frame->set_is_pasting(true); + render_widget->set_is_pasting(true); FALLTHROUGH; // Matches RenderFrameImpl::OnPaste() which sets both. case UpdateState::kIsSelectingRange: - render_frame->set_handling_select_range(true); + render_widget->set_handling_select_range(true); break; case UpdateState::kNone: break; @@ -488,10 +487,10 @@ FrameInputHandlerImpl::HandlingState::HandlingState( FrameInputHandlerImpl::HandlingState::~HandlingState() { // RenderFrame may have been destroyed while this object was on the stack. - if (!render_frame_) + if (!render_widget_) return; - render_frame_->set_handling_select_range(original_select_range_value_); - render_frame_->set_is_pasting(original_pasting_value_); + render_widget_->set_handling_select_range(original_select_range_value_); + render_widget_->set_is_pasting(original_pasting_value_); } } // namespace content diff --git a/chromium/content/renderer/input/frame_input_handler_impl.h b/chromium/content/renderer/input/frame_input_handler_impl.h index 7780f07a68e..052a8be277c 100644 --- a/chromium/content/renderer/input/frame_input_handler_impl.h +++ b/chromium/content/renderer/input/frame_input_handler_impl.h @@ -8,19 +8,19 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "content/common/input/input_handler.mojom.h" -#include "content/renderer/render_frame_impl.h" +#include "content/renderer/render_widget.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" namespace content { class MainThreadEventQueue; -// This class provides an implementation of FrameInputHandler mojo interface. -// When a compositor thread is being used in the renderer the mojo channel -// is bound on the compositor thread. Method calls, and events received on the -// compositor thread are then placed in the MainThreadEventQueue for -// the associated RenderWidget. This is done as to ensure that input related +// This class provides an implementation of FrameWidgetInputHandler mojo +// interface. When a compositor thread is being used in the renderer the mojo +// channel is bound on the compositor thread. Method calls, and events received +// on the compositor thread are then placed in the MainThreadEventQueue for the +// associated RenderWidget. This is done as to ensure that input related // messages and events that are handled on the compositor thread aren't // executed before other input events that need to be processed on the // main thread. ie. Since some messages flow to the compositor thread @@ -38,11 +38,14 @@ class MainThreadEventQueue; // // When a compositor thread isn't used the mojo channel is just bound // on the main thread and messages are handled right away. -class CONTENT_EXPORT FrameInputHandlerImpl : public mojom::FrameInputHandler { +class CONTENT_EXPORT FrameInputHandlerImpl + : public blink::mojom::FrameWidgetInputHandler { public: - static void CreateMojoService( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver); + FrameInputHandlerImpl( + base::WeakPtr<RenderWidget> widget, + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + scoped_refptr<MainThreadEventQueue> input_event_queue); + ~FrameInputHandlerImpl() override; void SetCompositionFromExistingText( int32_t start, @@ -78,48 +81,34 @@ class CONTENT_EXPORT FrameInputHandlerImpl : public mojom::FrameInputHandler { void MoveRangeSelectionExtent(const gfx::Point& extent) override; void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override; void MoveCaret(const gfx::Point& point) override; - void GetWidgetInputHandler( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) override; private: - ~FrameInputHandlerImpl() override; enum class UpdateState { kNone, kIsPasting, kIsSelectingRange }; class HandlingState { public: - HandlingState(const base::WeakPtr<RenderFrameImpl>& render_frame, + HandlingState(const base::WeakPtr<RenderWidget>& render_widget, UpdateState state); ~HandlingState(); private: - base::WeakPtr<RenderFrameImpl> render_frame_; + base::WeakPtr<RenderWidget> render_widget_; bool original_select_range_value_; bool original_pasting_value_; }; - FrameInputHandlerImpl( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver); - void RunOnMainThread(base::OnceClosure closure); - void BindNow(mojo::PendingReceiver<mojom::FrameInputHandler> receiver); - void ExecuteCommandOnMainThread(const std::string& command, - UpdateState state); + static void ExecuteCommandOnMainThread(base::WeakPtr<RenderWidget> widget, + const std::string& command, + UpdateState state); void Release(); - mojo::Receiver<mojom::FrameInputHandler> receiver_{this}; - - // |render_frame_| should only be accessed on the main thread. Use - // GetRenderFrame so that it will DCHECK this for you. - base::WeakPtr<RenderFrameImpl> render_frame_; + // |render_widget_| should only be accessed on the main thread. + base::WeakPtr<RenderWidget> widget_; scoped_refptr<MainThreadEventQueue> input_event_queue_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - base::WeakPtr<FrameInputHandlerImpl> weak_this_; - base::WeakPtrFactory<FrameInputHandlerImpl> weak_ptr_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(FrameInputHandlerImpl); }; diff --git a/chromium/content/renderer/input/input_event_prediction.cc b/chromium/content/renderer/input/input_event_prediction.cc index 30a63b7f73d..b6632a6a8b4 100644 --- a/chromium/content/renderer/input/input_event_prediction.cc +++ b/chromium/content/renderer/input/input_event_prediction.cc @@ -8,7 +8,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" -#include "content/public/common/content_features.h" +#include "third_party/blink/public/common/features.h" using blink::WebInputEvent; using blink::WebMouseEvent; @@ -44,10 +44,10 @@ InputEventPrediction::InputEventPrediction(bool enable_resampling) // flag. std::string predictor_name = enable_resampling_ - ? GetFieldTrialParamValueByFeature(features::kResamplingInputEvents, - "predictor") + ? GetFieldTrialParamValueByFeature( + blink::features::kResamplingInputEvents, "predictor") : GetFieldTrialParamValueByFeature( - features::kInputPredictorTypeChoice, "predictor"); + blink::features::kInputPredictorTypeChoice, "predictor"); if (predictor_name.empty()) selected_predictor_type_ = diff --git a/chromium/content/renderer/input/input_event_prediction_unittest.cc b/chromium/content/renderer/input/input_event_prediction_unittest.cc index 0ad1d1df08f..95c3b52b6bd 100644 --- a/chromium/content/renderer/input/input_event_prediction_unittest.cc +++ b/chromium/content/renderer/input/input_event_prediction_unittest.cc @@ -7,15 +7,16 @@ #include <string> #include "base/test/scoped_feature_list.h" -#include "content/common/input/synthetic_web_input_event_builders.h" -#include "content/public/common/content_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "ui/events/base_event_utils.h" namespace content { namespace { +using blink::SyntheticWebMouseEventBuilder; +using blink::SyntheticWebTouchEvent; using blink::WebInputEvent; using blink::WebMouseEvent; using blink::WebPointerProperties; @@ -28,7 +29,7 @@ class InputEventPredictionTest : public testing::Test { InputEventPredictionTest() { // Default to enable resampling with empty predictor for testing. ConfigureFieldTrialAndInitialize( - features::kResamplingInputEvents, + blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameEmpty); } @@ -70,7 +71,7 @@ class InputEventPredictionTest : public testing::Test { const std::string& predictor_type) { ConfigureFieldTrial(feature, predictor_type); event_predictor_ = std::make_unique<InputEventPrediction>( - base::FeatureList::IsEnabled(features::kResamplingInputEvents)); + base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents)); } protected: @@ -87,32 +88,32 @@ TEST_F(InputEventPredictionTest, PredictorType) { EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeEmpty); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameEmpty); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeEmpty); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameLsq); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeLsq); // Default to Kalman predictor. - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, ""); + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, ""); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); - ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, + ConfigureFieldTrialAndInitialize(blink::features::kInputPredictorTypeChoice, blink::features::kScrollPredictorNameLsq); EXPECT_FALSE(event_predictor_->enable_resampling_); // When enable_resampling_ is true, kInputPredictorTypeChoice flag has no @@ -285,7 +286,8 @@ TEST_F(InputEventPredictionTest, TouchScrollStartedRemoveAllTouchPoints) { TEST_F(InputEventPredictionTest, ResamplingDisabled) { // When resampling is disabled, default to use kalman filter. - ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, ""); + ConfigureFieldTrialAndInitialize(blink::features::kInputPredictorTypeChoice, + ""); EXPECT_FALSE(event_predictor_->enable_resampling_); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); @@ -321,7 +323,7 @@ TEST_F(InputEventPredictionTest, ResamplingDisabled) { // Test that when dt > maxResampling, resampling is cut off . TEST_F(InputEventPredictionTest, NoResampleWhenExceedMaxResampleTime) { - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); base::TimeDelta predictor_max_resample_time = @@ -397,7 +399,7 @@ TEST_F(InputEventPredictionTest, NoResampleWhenExceedMaxResampleTime) { // Test that when dt between events is 6ms, first predicted point is 6ms ahead. TEST_F(InputEventPredictionTest, PredictedEventsTimeIntervalEqualRealEvents) { - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); base::TimeTicks event_time = ui::EventTimeForNow(); diff --git a/chromium/content/renderer/input/main_thread_event_queue.cc b/chromium/content/renderer/input/main_thread_event_queue.cc index ac3ef9423a1..48bf221d93f 100644 --- a/chromium/content/renderer/input/main_thread_event_queue.cc +++ b/chromium/content/renderer/input/main_thread_event_queue.cc @@ -12,6 +12,7 @@ #include "content/common/input/event_with_latency_info.h" #include "content/common/input_messages.h" #include "content/renderer/render_widget.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/input/web_input_event_attribution.h" @@ -48,16 +49,14 @@ constexpr base::TimeDelta kAsyncTouchMoveInterval = } // namespace -class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, - public MainThreadEventQueueTask { +class QueuedWebInputEvent : public MainThreadEventQueueTask { public: - QueuedWebInputEvent(ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency, + QueuedWebInputEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event, bool originally_cancelable, HandledEventCallback callback, bool known_by_scheduler, const blink::WebInputEventAttribution& attribution) - : WebCoalescedInputEvent(std::move(event), latency), + : event_(std::move(event)), originally_cancelable_(originally_cancelable), callback_(std::move(callback)), known_by_scheduler_count_(known_by_scheduler ? 1 : 0), @@ -67,19 +66,21 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, bool AreCoalescablePointerRawUpdateEvents(QueuedWebInputEvent* other_event) { // There is no pointermove at this point in the queue. - DCHECK(Event().GetType() != WebInputEvent::Type::kPointerMove && - other_event->Event().GetType() != WebInputEvent::Type::kPointerMove); + DCHECK(event_->Event().GetType() != WebInputEvent::Type::kPointerMove && + other_event->event_->Event().GetType() != + WebInputEvent::Type::kPointerMove); // Events with modifiers differing by kRelativeMotionEvent should not be // coalesced. In case of a pointer lock, kRelativeMotionEvent is sent // when the cursor is recentered. Events post the recentered event have // a big delta compared to the previous events and hence should not be // coalesced. - return Event().GetType() == WebInputEvent::Type::kPointerRawUpdate && - other_event->Event().GetType() == + return event_->Event().GetType() == WebInputEvent::Type::kPointerRawUpdate && - ((Event().GetModifiers() & + other_event->event_->Event().GetType() == + WebInputEvent::Type::kPointerRawUpdate && + ((event_->Event().GetModifiers() & blink::WebInputEvent::Modifiers::kRelativeMotionEvent) == - (other_event->Event().GetModifiers() & + (other_event->event_->Event().GetModifiers() & blink::WebInputEvent::Modifiers::kRelativeMotionEvent)); } @@ -89,15 +90,15 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, QueuedWebInputEvent* other_event = static_cast<QueuedWebInputEvent*>(other_task); - if (other_event->Event().GetType() == + if (other_event->event_->Event().GetType() == blink::WebInputEvent::Type::kTouchScrollStarted) { return HandleTouchScrollStartQueued(); } - if (!Event().IsSameEventClass(other_event->Event())) + if (!event_->Event().IsSameEventClass(other_event->event_->Event())) return FilterResult::KeepIterating; - if (!CanCoalesceWith(*other_event)) { + if (!event_->CanCoalesceWith(*other_event->event_)) { // Two pointerevents may not be able to coalesce but we should continue // looking further down the queue if both of them were rawupdate or move // events and only their pointer_type, id, or event_type was different. @@ -117,11 +118,11 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, if (other_event->callback_) { blocking_coalesced_callbacks_.push_back( std::make_pair(std::move(other_event->callback_), - other_event->latency_info().trace_id())); + other_event->event_->latency_info().trace_id())); } known_by_scheduler_count_ += other_event->known_by_scheduler_count_; - CoalesceWith(*other_event); + event_->CoalesceWith(*other_event->event_); // The newest event (|other_item|) always wins when updating fields. originally_cancelable_ = other_event->originally_cancelable_; @@ -135,12 +136,12 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, HandledEventCallback callback = base::BindOnce(&QueuedWebInputEvent::HandledEvent, base::Unretained(this), base::RetainedRef(queue)); - if (!queue->HandleEventOnMainThread(*this, attribution(), + if (!queue->HandleEventOnMainThread(*event_, attribution(), std::move(callback))) { // The |callback| won't be run, so our stored |callback_| should run // indicating error. HandledEvent(queue, blink::mojom::InputEventResultState::kNotConsumed, - latency_info(), nullptr, base::nullopt); + event_->latency_info(), nullptr, base::nullopt); } } @@ -171,7 +172,7 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, // events processed. for (size_t i = 0; i < known_by_scheduler_count_; ++i) { queue->main_thread_scheduler_->DidHandleInputEventOnMainThread( - Event(), + event_->Event(), ack_result == blink::mojom::InputEventResultState::kConsumed ? blink::WebInputEventResult::kHandledApplication : blink::WebInputEventResult::kNotHandled); @@ -183,14 +184,20 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, blink::WebInputEventAttribution attribution() const { return attribution_; } + const blink::WebInputEvent& Event() const { return event_->Event(); } + + blink::WebCoalescedInputEvent* mutable_coalesced_event() { + return event_.get(); + } + private: FilterResult HandleTouchScrollStartQueued() { // A TouchScrollStart will queued after this touch move which will make all // previous touch moves that are queued uncancelable. - switch (Event().GetType()) { + switch (event_->Event().GetType()) { case blink::WebInputEvent::Type::kTouchMove: { blink::WebTouchEvent* touch_event = - static_cast<blink::WebTouchEvent*>(EventPointer()); + static_cast<blink::WebTouchEvent*>(event_->EventPointer()); if (touch_event->dispatch_type == blink::WebInputEvent::DispatchType::kBlocking) { touch_event->dispatch_type = @@ -206,6 +213,8 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, } } + std::unique_ptr<blink::WebCoalescedInputEvent> event_; + // Contains the pending callbacks to be called, along with their associated // trace_ids. base::circular_deque<std::pair<HandledEventCallback, int64_t>> @@ -246,20 +255,19 @@ MainThreadEventQueue::MainThreadEventQueue( raf_fallback_timer_.SetTaskRunner(main_task_runner); event_predictor_ = std::make_unique<InputEventPrediction>( - base::FeatureList::IsEnabled(features::kResamplingInputEvents)); + base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents)); } MainThreadEventQueue::~MainThreadEventQueue() {} void MainThreadEventQueue::HandleEvent( - ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency, + std::unique_ptr<blink::WebCoalescedInputEvent> event, InputEventDispatchType original_dispatch_type, blink::mojom::InputEventResultState ack_result, const blink::WebInputEventAttribution& attribution, HandledEventCallback callback) { TRACE_EVENT2("input", "MainThreadEventQueue::HandleEvent", "dispatch_type", - original_dispatch_type, "event_type", event->GetType()); + original_dispatch_type, "event_type", event->Event().GetType()); DCHECK(original_dispatch_type == DISPATCH_TYPE_BLOCKING || original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING); DCHECK(ack_result == blink::mojom::InputEventResultState::kSetNonBlocking || @@ -270,13 +278,15 @@ void MainThreadEventQueue::HandleEvent( bool is_blocking = original_dispatch_type == DISPATCH_TYPE_BLOCKING && ack_result != blink::mojom::InputEventResultState::kSetNonBlocking; - bool is_wheel = event->GetType() == blink::WebInputEvent::Type::kMouseWheel; - bool is_touch = blink::WebInputEvent::IsTouchEventType(event->GetType()); + bool is_wheel = + event->Event().GetType() == blink::WebInputEvent::Type::kMouseWheel; + bool is_touch = + blink::WebInputEvent::IsTouchEventType(event->Event().GetType()); bool originally_cancelable = false; if (is_touch) { blink::WebTouchEvent* touch_event = - static_cast<blink::WebTouchEvent*>(event.get()); + static_cast<blink::WebTouchEvent*>(event->EventPointer()); originally_cancelable = touch_event->dispatch_type == blink::WebInputEvent::DispatchType::kBlocking; @@ -313,7 +323,7 @@ void MainThreadEventQueue::HandleEvent( if (is_wheel) { blink::WebMouseWheelEvent* wheel_event = - static_cast<blink::WebMouseWheelEvent*>(event.get()); + static_cast<blink::WebMouseWheelEvent*>(event->EventPointer()); originally_cancelable = wheel_event->dispatch_type == blink::WebInputEvent::DispatchType::kBlocking; if (!is_blocking) { @@ -331,26 +341,33 @@ void MainThreadEventQueue::HandleEvent( } if (has_pointerrawupdate_handlers_) { - if (event->GetType() == WebInputEvent::Type::kMouseMove) { - ui::WebScopedInputEvent raw_event(new blink::WebPointerEvent( - WebInputEvent::Type::kPointerRawUpdate, - *(static_cast<blink::WebMouseEvent*>(event.get())))); + if (event->Event().GetType() == WebInputEvent::Type::kMouseMove) { + std::unique_ptr<blink::WebCoalescedInputEvent> raw_event = + std::make_unique<blink::WebCoalescedInputEvent>( + std::make_unique<blink::WebPointerEvent>( + WebInputEvent::Type::kPointerRawUpdate, + *(static_cast<blink::WebMouseEvent*>(event->EventPointer()))), + event->latency_info()); std::unique_ptr<QueuedWebInputEvent> raw_queued_event( - new QueuedWebInputEvent(std::move(raw_event), latency, false, + new QueuedWebInputEvent(std::move(raw_event), false, HandledEventCallback(), false, attribution)); QueueEvent(std::move(raw_queued_event)); - } else if (event->GetType() == WebInputEvent::Type::kTouchMove) { + } else if (event->Event().GetType() == WebInputEvent::Type::kTouchMove) { const blink::WebTouchEvent& touch_event = - *static_cast<const blink::WebTouchEvent*>(event.get()); + *static_cast<const blink::WebTouchEvent*>(event->EventPointer()); for (unsigned i = 0; i < touch_event.touches_length; ++i) { const blink::WebTouchPoint& touch_point = touch_event.touches[i]; if (touch_point.state == blink::WebTouchPoint::State::kStateMoved) { - ui::WebScopedInputEvent raw_event( - new blink::WebPointerEvent(touch_event, touch_point)); - raw_event->SetType(WebInputEvent::Type::kPointerRawUpdate); + std::unique_ptr<blink::WebCoalescedInputEvent> raw_event = + std::make_unique<blink::WebCoalescedInputEvent>( + std::make_unique<blink::WebPointerEvent>(touch_event, + touch_point), + event->latency_info()); + raw_event->EventPointer()->SetType( + WebInputEvent::Type::kPointerRawUpdate); std::unique_ptr<QueuedWebInputEvent> raw_queued_event( - new QueuedWebInputEvent(std::move(raw_event), latency, false, + new QueuedWebInputEvent(std::move(raw_event), false, HandledEventCallback(), false, attribution)); QueueEvent(std::move(raw_queued_event)); @@ -359,15 +376,21 @@ void MainThreadEventQueue::HandleEvent( } } + ui::LatencyInfo cloned_latency_info; + + // Clone the latency info if we are calling the callback. + if (callback) + cloned_latency_info = event->latency_info(); + std::unique_ptr<QueuedWebInputEvent> queued_event(new QueuedWebInputEvent( - std::move(event), latency, originally_cancelable, - std::move(event_callback), IsForwardedAndSchedulerKnown(ack_result), - attribution)); + std::move(event), originally_cancelable, std::move(event_callback), + IsForwardedAndSchedulerKnown(ack_result), attribution)); QueueEvent(std::move(queued_event)); if (callback) - std::move(callback).Run(ack_result, latency, nullptr, base::nullopt); + std::move(callback).Run(ack_result, cloned_latency_info, nullptr, + base::nullopt); } void MainThreadEventQueue::QueueClosure(base::OnceClosure closure) { @@ -621,7 +644,8 @@ void MainThreadEventQueue::HandleEventResampling( base::TimeTicks frame_time) { if (item->IsWebInputEvent() && allow_raf_aligned_input_ && event_predictor_) { QueuedWebInputEvent* event = static_cast<QueuedWebInputEvent*>(item.get()); - event_predictor_->HandleEvents(*event, frame_time); + event_predictor_->HandleEvents(*event->mutable_coalesced_event(), + frame_time); } } diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h index 8f338767dbc..02efe76b16d 100644 --- a/chromium/content/renderer/input/main_thread_event_queue.h +++ b/chromium/content/renderer/input/main_thread_event_queue.h @@ -90,8 +90,7 @@ class CONTENT_EXPORT MainThreadEventQueue // Called once the compositor has handled |event| and indicated that it is // a non-blocking event to be queued to the main thread. - void HandleEvent(ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency, + void HandleEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event, InputEventDispatchType dispatch_type, blink::mojom::InputEventResultState ack_result, const blink::WebInputEventAttribution& attribution, diff --git a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc index 69894a688df..67207dfd5c0 100644 --- a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc +++ b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc @@ -17,13 +17,16 @@ #include "base/test/scoped_feature_list.h" #include "base/test/test_simple_task_runner.h" #include "build/build_config.h" -#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/renderer/input/main_thread_event_queue.h" #include "content/renderer/render_thread_impl.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/web_input_event_attribution.h" #include "third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h" +using blink::SyntheticWebMouseEventBuilder; +using blink::SyntheticWebMouseWheelEventBuilder; +using blink::SyntheticWebTouchEvent; using blink::WebInputEvent; using blink::WebMouseEvent; using blink::WebMouseWheelEvent; @@ -198,9 +201,11 @@ class MainThreadEventQueueTest : public testing::Test, blink::mojom::InputEventResultState ack_result) { base::AutoReset<bool> in_handle_event(&handler_callback_->handling_event_, true); - queue_->HandleEvent( - event.Clone(), ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING, ack_result, - blink::WebInputEventAttribution(), handler_callback_->GetCallback()); + queue_->HandleEvent(std::make_unique<blink::WebCoalescedInputEvent>( + event.Clone(), ui::LatencyInfo()), + DISPATCH_TYPE_BLOCKING, ack_result, + blink::WebInputEventAttribution(), + handler_callback_->GetCallback()); } void RunClosure(unsigned closure_id) { @@ -370,8 +375,6 @@ TEST_F(MainThreadEventQueueTest, NonBlockingWheel) { handled_tasks_[0]->taskAsEvent()->GetCoalescedEventsPointers(); const WebMouseWheelEvent* coalesced_wheel_event0 = static_cast<const WebMouseWheelEvent*>(coalesced_events[0].get()); - coalesced_event.dispatch_type = - WebInputEvent::DispatchType::kListenersNonBlockingPassive; EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event0)); coalesced_event = kEvents[1]; @@ -399,8 +402,6 @@ TEST_F(MainThreadEventQueueTest, NonBlockingWheel) { handled_tasks_[1]->taskAsEvent()->GetCoalescedEventsPointers(); const WebMouseWheelEvent* coalesced_wheel_event0 = static_cast<const WebMouseWheelEvent*>(coalesced_events[0].get()); - coalesced_event.dispatch_type = - WebInputEvent::DispatchType::kListenersNonBlockingPassive; EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event0)); coalesced_event = kEvents[3]; @@ -444,9 +445,10 @@ TEST_F(MainThreadEventQueueTest, NonBlockingTouch) { handled_tasks_.at(0)->taskAsEvent()->Event().GetType()); const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>( handled_tasks_.at(0)->taskAsEvent()->EventPointer()); - kEvents[0].dispatch_type = + SyntheticWebTouchEvent non_blocking_touch = kEvents[0]; + non_blocking_touch.dispatch_type = WebInputEvent::DispatchType::kListenersNonBlockingPassive; - EXPECT_TRUE(Equal(kEvents[0], *last_touch_event)); + EXPECT_TRUE(Equal(non_blocking_touch, *last_touch_event)); { EXPECT_EQ(1u, handled_tasks_[0]->taskAsEvent()->CoalescedEventSize()); @@ -462,9 +464,10 @@ TEST_F(MainThreadEventQueueTest, NonBlockingTouch) { handled_tasks_.at(1)->taskAsEvent()->Event().GetType()); last_touch_event = static_cast<const WebTouchEvent*>( handled_tasks_.at(1)->taskAsEvent()->EventPointer()); - kEvents[1].dispatch_type = + non_blocking_touch = kEvents[1]; + non_blocking_touch.dispatch_type = WebInputEvent::DispatchType::kListenersNonBlockingPassive; - EXPECT_TRUE(Equal(kEvents[1], *last_touch_event)); + EXPECT_TRUE(Equal(non_blocking_touch, *last_touch_event)); { EXPECT_EQ(1u, handled_tasks_[1]->taskAsEvent()->CoalescedEventSize()); @@ -493,8 +496,6 @@ TEST_F(MainThreadEventQueueTest, NonBlockingTouch) { handled_tasks_[2]->taskAsEvent()->GetCoalescedEventsPointers(); const WebTouchEvent* coalesced_touch_event0 = static_cast<const WebTouchEvent*>(coalesced_events[0].get()); - coalesced_event.dispatch_type = - WebInputEvent::DispatchType::kListenersNonBlockingPassive; EXPECT_TRUE(Equal(coalesced_event, *coalesced_touch_event0)); coalesced_event = kEvents[3]; @@ -1493,4 +1494,103 @@ TEST_F(MainThreadEventQueueTest, UnbufferedDispatchMouseEvent) { EXPECT_FALSE(needs_main_frame_); } +// This test verifies that the events marked with kRelativeMotionEvent modifier +// are not coalesced with other events. During pointer lock, +// kRelativeMotionEvent is sent to the Renderer only to update the new screen +// position. Events of this kind shouldn't be dispatched or coalesced. +TEST_F(MainThreadEventQueueTest, PointerEventsWithRelativeMotionCoalescing) { + WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build( + WebInputEvent::Type::kMouseMove, 10, 10, 0); + + EXPECT_FALSE(main_task_runner_->HasPendingTask()); + EXPECT_EQ(0u, event_queue().size()); + + // Non blocking events are not reported to the scheduler. + EXPECT_CALL(thread_scheduler_, + DidHandleInputEventOnMainThread(testing::_, testing::_)) + .Times(0); + + queue_->HasPointerRawUpdateEventHandlers(true); + + // Inject two mouse move events. For each event injected, there will be two + // events in the queue. One for kPointerRawUpdate and another kMouseMove + // event. + HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(2u, event_queue().size()); + // When another event of the same kind is injected, it is coalesced with the + // previous event, hence queue size doesn't change. + HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(2u, event_queue().size()); + + // Inject a kRelativeMotionEvent, which cannot be coalesced. Thus, the queue + // size should increase. + WebMouseEvent fake_mouse_move = SyntheticWebMouseEventBuilder::Build( + WebInputEvent::Type::kMouseMove, 10, 10, + blink::WebInputEvent::Modifiers::kRelativeMotionEvent); + HandleEvent(fake_mouse_move, + blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(4u, event_queue().size()); + + // Lastly inject another mouse move event. Since it cannot be coalesced with + // previous event, which is a kRelativeMotionEvent, expect the queue size to + // increase again. + HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(6u, event_queue().size()); + + RunPendingTasksWithSimulatedRaf(); + EXPECT_EQ(0u, event_queue().size()); + EXPECT_FALSE(needs_main_frame_); + EXPECT_FALSE(main_task_runner_->HasPendingTask()); + + // For the 4 events injected, verify that the queue size should be 6, that is + // 3 kPointerRawUpdate events and 3 kMouseMove events. + EXPECT_EQ(6u, handled_tasks_.size()); + { + // The first event should have a |CoalescedEventSize| of 2, since two events + // of the same kind are coalesced. + EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate, + handled_tasks_.at(0)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(2u, handled_tasks_.at(0)->taskAsEvent()->CoalescedEventSize()); + } + { + // The second event is a kRelativeMotionEvent, it cannot be coalesced, so + // the |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate, + handled_tasks_.at(1)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(1)->taskAsEvent()->CoalescedEventSize()); + EXPECT_EQ(blink::WebInputEvent::Modifiers::kRelativeMotionEvent, + handled_tasks_.at(1)->taskAsEvent()->Event().GetModifiers()); + } + { + // The third event cannot be coalesced with the previous kPointerRawUpdate, + // so |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate, + handled_tasks_.at(2)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(2)->taskAsEvent()->CoalescedEventSize()); + } + { + // The fourth event should have a |CoalescedEventSize| of 2, since two + // events of the same kind are coalesced. + EXPECT_EQ(WebInputEvent::Type::kMouseMove, + handled_tasks_.at(3)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(2u, handled_tasks_.at(3)->taskAsEvent()->CoalescedEventSize()); + } + { + // The fifth event is a kRelativeMotionEvent, it cannot be coalesced, so + // the |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kMouseMove, + handled_tasks_.at(4)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(4)->taskAsEvent()->CoalescedEventSize()); + EXPECT_EQ(blink::WebInputEvent::Modifiers::kRelativeMotionEvent, + handled_tasks_.at(4)->taskAsEvent()->Event().GetModifiers()); + } + { + // The sixth event cannot be coalesced with the previous kMouseMove, + // so |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kMouseMove, + handled_tasks_.at(5)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(5)->taskAsEvent()->CoalescedEventSize()); + } +} + } // namespace content diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc deleted file mode 100644 index a3ce13879aa..00000000000 --- a/chromium/content/renderer/input/render_widget_input_handler.cc +++ /dev/null @@ -1,730 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/input/render_widget_input_handler.h" - -#include <stddef.h> -#include <stdint.h> -#include <utility> - -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "base/metrics/histogram_macros.h" -#include "build/build_config.h" -#include "cc/metrics/event_metrics.h" -#include "cc/paint/element_id.h" -#include "cc/trees/latency_info_swap_promise_monitor.h" -#include "components/viz/common/surfaces/frame_sink_id.h" -#include "content/public/common/content_switches.h" -#include "content/public/renderer/render_frame.h" -#include "content/renderer/ime_event_guard.h" -#include "content/renderer/input/render_widget_input_handler_delegate.h" -#include "content/renderer/render_frame_proxy.h" -#include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_widget.h" -#include "services/tracing/public/cpp/perfetto/flow_event_utils.h" -#include "services/tracing/public/cpp/perfetto/macros.h" -#include "third_party/blink/public/common/input/web_gesture_device.h" -#include "third_party/blink/public/common/input/web_gesture_event.h" -#include "third_party/blink/public/common/input/web_input_event_attribution.h" -#include "third_party/blink/public/common/input/web_keyboard_event.h" -#include "third_party/blink/public/common/input/web_mouse_wheel_event.h" -#include "third_party/blink/public/common/input/web_pointer_event.h" -#include "third_party/blink/public/common/input/web_touch_event.h" -#include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" -#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" -#include "third_party/blink/public/web/web_document.h" -#include "third_party/blink/public/web/web_frame_widget.h" -#include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_node.h" -#include "ui/events/blink/blink_event_util.h" -#include "ui/events/blink/web_input_event_traits.h" -#include "ui/gfx/geometry/dip_util.h" -#include "ui/gfx/geometry/point_conversions.h" -#include "ui/latency/latency_info.h" - -#if defined(OS_ANDROID) -#include <android/keycodes.h> -#endif - -using blink::WebGestureEvent; -using blink::WebInputEvent; -using blink::WebInputEventResult; -using blink::WebKeyboardEvent; -using blink::WebMouseEvent; -using blink::WebMouseWheelEvent; -using blink::WebPointerEvent; -using blink::WebTouchEvent; -using blink::WebTouchPoint; -using perfetto::protos::pbzero::ChromeLatencyInfo; -using perfetto::protos::pbzero::TrackEvent; -using ui::DidOverscrollParams; - -namespace content { - -namespace { - -int64_t GetEventLatencyMicros(base::TimeTicks event_timestamp, - base::TimeTicks now) { - return (now - event_timestamp).InMicroseconds(); -} - -void LogInputEventLatencyUma(const WebInputEvent& event, base::TimeTicks now) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Event.AggregatedLatency.Renderer2", - GetEventLatencyMicros(event.TimeStamp(), now), 1, - 10000000, 100); -} - -void LogPassiveEventListenersUma(WebInputEventResult result, - WebInputEvent::DispatchType dispatch_type) { - // This enum is backing a histogram. Do not remove or reorder members. - enum ListenerEnum { - PASSIVE_LISTENER_UMA_ENUM_PASSIVE, - PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE, - PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED, - PASSIVE_LISTENER_UMA_ENUM_CANCELABLE, - PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED, - PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING, - PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS_DEPRECATED, - PASSIVE_LISTENER_UMA_ENUM_COUNT - }; - - ListenerEnum enum_value; - switch (dispatch_type) { - case WebInputEvent::DispatchType::kListenersForcedNonBlockingDueToFling: - enum_value = PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING; - break; - case WebInputEvent::DispatchType::kListenersNonBlockingPassive: - enum_value = PASSIVE_LISTENER_UMA_ENUM_PASSIVE; - break; - case WebInputEvent::DispatchType::kEventNonBlocking: - enum_value = PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE; - break; - case WebInputEvent::DispatchType::kBlocking: - if (result == WebInputEventResult::kHandledApplication) - enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED; - else if (result == WebInputEventResult::kHandledSuppressed) - enum_value = PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED; - else - enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE; - break; - default: - NOTREACHED(); - return; - } - - UMA_HISTOGRAM_ENUMERATION("Event.PassiveListeners", enum_value, - PASSIVE_LISTENER_UMA_ENUM_COUNT); -} - -void LogAllPassiveEventListenersUma(const WebInputEvent& input_event, - WebInputEventResult result) { - // TODO(dtapuska): Use the input_event.timeStampSeconds as the start - // ideally this should be when the event was sent by the compositor to the - // renderer. https://crbug.com/565348. - if (input_event.GetType() == WebInputEvent::Type::kTouchStart || - input_event.GetType() == WebInputEvent::Type::kTouchMove || - input_event.GetType() == WebInputEvent::Type::kTouchEnd) { - const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event); - - LogPassiveEventListenersUma(result, touch.dispatch_type); - } else if (input_event.GetType() == WebInputEvent::Type::kMouseWheel) { - LogPassiveEventListenersUma( - result, - static_cast<const WebMouseWheelEvent&>(input_event).dispatch_type); - } -} - -blink::WebCoalescedInputEvent GetCoalescedWebPointerEventForTouch( - const WebPointerEvent& pointer_event, - const std::vector<std::unique_ptr<WebInputEvent>>& coalesced_events, - const std::vector<std::unique_ptr<WebInputEvent>>& predicted_events, - const ui::LatencyInfo& latency) { - std::vector<std::unique_ptr<WebInputEvent>> related_pointer_events; - for (const std::unique_ptr<WebInputEvent>& event : coalesced_events) { - DCHECK(WebInputEvent::IsTouchEventType(event->GetType())); - const WebTouchEvent& touch_event = - static_cast<const WebTouchEvent&>(*event); - for (unsigned i = 0; i < touch_event.touches_length; ++i) { - if (touch_event.touches[i].id == pointer_event.id && - touch_event.touches[i].state != - WebTouchPoint::State::kStateStationary) { - related_pointer_events.emplace_back(std::make_unique<WebPointerEvent>( - touch_event, touch_event.touches[i])); - } - } - } - std::vector<std::unique_ptr<WebInputEvent>> predicted_pointer_events; - for (const std::unique_ptr<WebInputEvent>& event : predicted_events) { - DCHECK(WebInputEvent::IsTouchEventType(event->GetType())); - const WebTouchEvent& touch_event = - static_cast<const WebTouchEvent&>(*event); - for (unsigned i = 0; i < touch_event.touches_length; ++i) { - if (touch_event.touches[i].id == pointer_event.id && - touch_event.touches[i].state != - WebTouchPoint::State::kStateStationary) { - predicted_pointer_events.emplace_back(std::make_unique<WebPointerEvent>( - touch_event, touch_event.touches[i])); - } - } - } - - return blink::WebCoalescedInputEvent( - pointer_event.Clone(), std::move(related_pointer_events), - std::move(predicted_pointer_events), latency); -} - -viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebHitTestResult& result) { - const blink::WebNode& node = result.GetNode(); - DCHECK(!node.IsNull()); - blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node); - if (!result_frame || !result_frame->IsWebRemoteFrame()) - return viz::FrameSinkId(); - - blink::WebRemoteFrame* remote_frame = result_frame->ToWebRemoteFrame(); - if (remote_frame->IsIgnoredForHitTest() || !result.ContentBoxContainsPoint()) - return viz::FrameSinkId(); - - return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id(); -} - -blink::mojom::InputEventResultState GetAckResult( - WebInputEventResult processed) { - return processed == WebInputEventResult::kNotHandled - ? blink::mojom::InputEventResultState::kNotConsumed - : blink::mojom::InputEventResultState::kConsumed; -} - -} // namespace - -// This class should be placed on the stack when handling an input event. It -// stores information from callbacks from blink while handling an input event -// and allows them to be returned in the InputEventAck result. -class RenderWidgetInputHandler::HandlingState { - public: - HandlingState(base::WeakPtr<RenderWidgetInputHandler> input_handler_param, - blink::WebInputEvent::Type type) - : event_type(type), input_handler(std::move(input_handler_param)) { - previous_was_handling_input = input_handler->handling_input_event_; - previous_state = input_handler->handling_input_state_; - input_handler->handling_input_event_ = true; - input_handler->handling_input_state_ = this; - } - - ~HandlingState() { - // Unwinding the HandlingState on the stack might result in an - // input_handler_ that got destroyed. i.e. via a nested event loop. - if (!input_handler) - return; - input_handler->handling_input_event_ = previous_was_handling_input; - DCHECK_EQ(input_handler->handling_input_state_, this); - input_handler->handling_input_state_ = previous_state; - } - - // Used to intercept overscroll notifications while an event is being - // handled. If the event causes overscroll, the overscroll metadata can be - // bundled in the event ack, saving an IPC. Note that we must continue - // supporting overscroll IPC notifications due to fling animation updates. - blink::mojom::DidOverscrollParamsPtr event_overscroll; - - base::Optional<cc::TouchAction> touch_action; - - // Used to hold a sequence of parameters corresponding to scroll gesture - // events that should be injected once the current input event is done - // being processed. - std::unique_ptr< - std::vector<RenderWidgetInputHandler::InjectScrollGestureParams>> - injected_scroll_params; - - // Type of the input event we are currently handling. - blink::WebInputEvent::Type event_type; - - private: - HandlingState* previous_state; - bool previous_was_handling_input; - base::WeakPtr<RenderWidgetInputHandler> input_handler; -}; - -RenderWidgetInputHandler::RenderWidgetInputHandler( - RenderWidgetInputHandlerDelegate* delegate, - RenderWidget* widget) - : delegate_(delegate), widget_(widget) { - DCHECK(delegate); - DCHECK(widget); - delegate->SetInputHandler(this); -} - -RenderWidgetInputHandler::~RenderWidgetInputHandler() = default; - -blink::WebHitTestResult RenderWidgetInputHandler::GetHitTestResultAtPoint( - const gfx::PointF& point) { - gfx::PointF point_in_pixel(point); - if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) { - point_in_pixel = gfx::ConvertPointToPixel( - widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel); - } - return widget_->GetWebWidget()->HitTestResultAt(point_in_pixel); -} - -viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint( - const gfx::PointF& point, - gfx::PointF* local_point) { - blink::WebHitTestResult result = GetHitTestResultAtPoint(point); - - blink::WebNode result_node = result.GetNode(); - *local_point = gfx::PointF(point); - - // TODO(crbug.com/797828): When the node is null the caller may - // need to do extra checks. Like maybe update the layout and then - // call the hit-testing API. Either way it might be better to have - // a DCHECK for the node rather than a null check here. - if (result_node.IsNull()) { - return widget_->GetFrameSinkId(); - } - - viz::FrameSinkId frame_sink_id = GetRemoteFrameSinkId(result); - if (frame_sink_id.is_valid()) { - *local_point = gfx::PointF(result.LocalPointWithoutContentBoxOffset()); - if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) { - *local_point = gfx::ConvertPointToDIP( - widget_->GetOriginalScreenInfo().device_scale_factor, *local_point); - } - return frame_sink_id; - } - - // Return the FrameSinkId for the current widget if the point did not hit - // test to a remote frame, or the point is outside of the remote frame's - // content box, or the remote frame doesn't have a valid FrameSinkId yet. - return widget_->GetFrameSinkId(); -} - -WebInputEventResult RenderWidgetInputHandler::HandleTouchEvent( - const blink::WebCoalescedInputEvent& coalesced_event) { - const WebInputEvent& input_event = coalesced_event.Event(); - - if (input_event.GetType() == WebInputEvent::Type::kTouchScrollStarted) { - WebPointerEvent pointer_event = - WebPointerEvent::CreatePointerCausesUaActionEvent( - blink::WebPointerProperties::PointerType::kUnknown, - input_event.TimeStamp()); - return widget_->GetWebWidget()->HandleInputEvent( - blink::WebCoalescedInputEvent(pointer_event, - coalesced_event.latency_info())); - } - - const WebTouchEvent touch_event = - static_cast<const WebTouchEvent&>(input_event); - for (unsigned i = 0; i < touch_event.touches_length; ++i) { - const WebTouchPoint& touch_point = touch_event.touches[i]; - if (touch_point.state != blink::WebTouchPoint::State::kStateStationary) { - const WebPointerEvent& pointer_event = - WebPointerEvent(touch_event, touch_point); - const blink::WebCoalescedInputEvent& coalesced_pointer_event = - GetCoalescedWebPointerEventForTouch( - pointer_event, coalesced_event.GetCoalescedEventsPointers(), - coalesced_event.GetPredictedEventsPointers(), - coalesced_event.latency_info()); - widget_->GetWebWidget()->HandleInputEvent(coalesced_pointer_event); - } - } - return widget_->GetWebWidget()->DispatchBufferedTouchEvents(); -} - -void RenderWidgetInputHandler::HandleInputEvent( - const blink::WebCoalescedInputEvent& coalesced_event, - HandledEventCallback callback) { - const WebInputEvent& input_event = coalesced_event.Event(); - - // Keep a WeakPtr to this RenderWidgetInputHandler to detect if executing the - // input event destroyed the associated RenderWidget (and this handler). - base::WeakPtr<RenderWidgetInputHandler> weak_self = - weak_ptr_factory_.GetWeakPtr(); - HandlingState handling_state(weak_self, input_event.GetType()); - -#if defined(OS_ANDROID) - ImeEventGuard guard(widget_->AsWeakPtr()); -#endif - - base::TimeTicks start_time; - if (base::TimeTicks::IsHighResolution()) - start_time = base::TimeTicks::Now(); - - TRACE_EVENT1("renderer,benchmark,rail", - "RenderWidgetInputHandler::OnHandleInputEvent", "event", - WebInputEvent::GetName(input_event.GetType())); - int64_t trace_id = coalesced_event.latency_info().trace_id(); - TRACE_EVENT("input,benchmark", "LatencyInfo.Flow", - [trace_id](perfetto::EventContext ctx) { - ChromeLatencyInfo* info = - ctx.event()->set_chrome_latency_info(); - info->set_trace_id(trace_id); - info->set_step(ChromeLatencyInfo::STEP_HANDLE_INPUT_EVENT_MAIN); - tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT, - trace_id); - }); - - // If we don't have a high res timer, these metrics won't be accurate enough - // to be worth collecting. Note that this does introduce some sampling bias. - if (!start_time.is_null()) - LogInputEventLatencyUma(input_event, start_time); - - ui::LatencyInfo swap_latency_info(coalesced_event.latency_info()); - swap_latency_info.AddLatencyNumber( - ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT); - cc::LatencyInfoSwapPromiseMonitor swap_promise_monitor( - &swap_latency_info, widget_->layer_tree_host()->GetSwapPromiseManager(), - nullptr); - auto scoped_event_metrics_monitor = - widget_->layer_tree_host()->GetScopedEventMetricsMonitor( - cc::EventMetrics::Create(input_event.GetTypeAsUiEventType(), - input_event.TimeStamp(), - input_event.GetScrollInputType())); - - bool prevent_default = false; - bool show_virtual_keyboard_for_mouse = false; - if (WebInputEvent::IsMouseEventType(input_event.GetType())) { - const WebMouseEvent& mouse_event = - static_cast<const WebMouseEvent&>(input_event); - TRACE_EVENT2("renderer", "HandleMouseMove", "x", - mouse_event.PositionInWidget().x(), "y", - mouse_event.PositionInWidget().y()); - - prevent_default = delegate_->WillHandleMouseEvent(mouse_event); - - // Reset the last known cursor if mouse has left this widget. So next - // time that the mouse enters we always set the cursor accordingly. - if (mouse_event.GetType() == WebInputEvent::Type::kMouseLeave) - current_cursor_.reset(); - - if (mouse_event.button == WebPointerProperties::Button::kLeft && - mouse_event.GetType() == WebInputEvent::Type::kMouseUp) { - show_virtual_keyboard_for_mouse = true; - } - } - - if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) { -#if defined(OS_ANDROID) - // The DPAD_CENTER key on Android has a dual semantic: (1) in the general - // case it should behave like a select key (i.e. causing a click if a button - // is focused). However, if a text field is focused (2), its intended - // behavior is to just show the IME and don't propagate the key. - // A typical use case is a web form: the DPAD_CENTER should bring up the IME - // when clicked on an input text field and cause the form submit if clicked - // when the submit button is focused, but not vice-versa. - // The UI layer takes care of translating DPAD_CENTER into a RETURN key, - // but at this point we have to swallow the event for the scenario (2). - const WebKeyboardEvent& key_event = - static_cast<const WebKeyboardEvent&>(input_event); - if (key_event.native_key_code == AKEYCODE_DPAD_CENTER && - widget_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) { - // Show the keyboard on keyup (not keydown) to match the behavior of - // Android's TextView. - if (key_event.GetType() == WebInputEvent::Type::kKeyUp) - widget_->ShowVirtualKeyboardOnElementFocus(); - // Prevent default for both keydown and keyup (letting the keydown go - // through to the web app would cause compatibility problems since - // DPAD_CENTER is also used as a "confirm" button). - prevent_default = true; - } -#endif - } - - if (WebInputEvent::IsGestureEventType(input_event.GetType())) { - const WebGestureEvent& gesture_event = - static_cast<const WebGestureEvent&>(input_event); - prevent_default = - prevent_default || delegate_->WillHandleGestureEvent(gesture_event); - } - - WebInputEventResult processed = prevent_default - ? WebInputEventResult::kHandledSuppressed - : WebInputEventResult::kNotHandled; - if (input_event.GetType() != WebInputEvent::Type::kChar || - !suppress_next_char_events_) { - suppress_next_char_events_ = false; - if (processed == WebInputEventResult::kNotHandled && - widget_->GetWebWidget()) { - if (delegate_->SupportsBufferedTouchEvents() && - WebInputEvent::IsTouchEventType(input_event.GetType())) - processed = HandleTouchEvent(coalesced_event); - else - processed = widget_->GetWebWidget()->HandleInputEvent(coalesced_event); - } - - // The associated RenderWidget (and this RenderWidgetInputHandler) could - // have been destroyed. If it was return early before accessing any more of - // this class. - if (!weak_self) { - if (callback) { - std::move(callback).Run(GetAckResult(processed), swap_latency_info, - std::move(handling_state.event_overscroll), - handling_state.touch_action); - } - return; - } - } - - // Handling |input_event| is finished and further down, we might start - // handling injected scroll events. So, stop monitoring EventMetrics for - // |input_event| to avoid nested monitors. - scoped_event_metrics_monitor = nullptr; - - LogAllPassiveEventListenersUma(input_event, processed); - - // If this RawKeyDown event corresponds to a browser keyboard shortcut and - // it's not processed by webkit, then we need to suppress the upcoming Char - // events. - bool is_keyboard_shortcut = - input_event.GetType() == WebInputEvent::Type::kRawKeyDown && - static_cast<const WebKeyboardEvent&>(input_event).is_browser_shortcut; - if (processed == WebInputEventResult::kNotHandled && is_keyboard_shortcut) - suppress_next_char_events_ = true; - - // The handling of some input events on the main thread may require injecting - // scroll gestures back into blink, e.g., a mousedown on a scrollbar. We - // do this here so that we can attribute latency information from the mouse as - // a scroll interaction, instead of just classifying as mouse input. - if (handling_state.injected_scroll_params && - handling_state.injected_scroll_params->size()) { - HandleInjectedScrollGestures( - std::move(*handling_state.injected_scroll_params), input_event, - coalesced_event.latency_info()); - } - - // Send gesture scroll events and their dispositions to the compositor thread, - // so that they can be used to produce the elastic overscroll effect. - if (input_event.GetType() == WebInputEvent::Type::kGestureScrollBegin || - input_event.GetType() == WebInputEvent::Type::kGestureScrollEnd || - input_event.GetType() == WebInputEvent::Type::kGestureScrollUpdate) { - const WebGestureEvent& gesture_event = - static_cast<const WebGestureEvent&>(input_event); - if (gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchpad || - gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchscreen) { - gfx::Vector2dF latest_overscroll_delta = - handling_state.event_overscroll - ? handling_state.event_overscroll->latest_overscroll_delta - : gfx::Vector2dF(); - cc::OverscrollBehavior overscroll_behavior = - handling_state.event_overscroll - ? handling_state.event_overscroll->overscroll_behavior - : cc::OverscrollBehavior(); - delegate_->ObserveGestureEventAndResult( - gesture_event, latest_overscroll_delta, overscroll_behavior, - processed != WebInputEventResult::kNotHandled); - } - } - - if (callback) { - std::move(callback).Run(GetAckResult(processed), swap_latency_info, - std::move(handling_state.event_overscroll), - handling_state.touch_action); - } else { - DCHECK(!handling_state.event_overscroll) - << "Unexpected overscroll for un-acked event"; - } - - // Show the virtual keyboard if enabled and a user gesture triggers a focus - // change. - if ((processed != WebInputEventResult::kNotHandled && - input_event.GetType() == WebInputEvent::Type::kTouchEnd) || - show_virtual_keyboard_for_mouse) { - delegate_->ShowVirtualKeyboard(); - } - - if (!prevent_default && - WebInputEvent::IsKeyboardEventType(input_event.GetType())) - delegate_->OnDidHandleKeyEvent(); - -// TODO(rouslan): Fix ChromeOS and Windows 8 behavior of autofill popup with -// virtual keyboard. -#if !defined(OS_ANDROID) - // Virtual keyboard is not supported, so react to focus change immediately. - if ((processed != WebInputEventResult::kNotHandled && - input_event.GetType() == WebInputEvent::Type::kMouseDown) || - input_event.GetType() == WebInputEvent::Type::kGestureTap) { - delegate_->FocusChangeComplete(); - } -#endif - - // Ensure all injected scrolls were handled or queue up - any remaining - // injected scrolls at this point would not be processed. - DCHECK(!handling_state.injected_scroll_params || - (handling_state.injected_scroll_params)->empty()); -} - -void RenderWidgetInputHandler::DidOverscrollFromBlink( - const gfx::Vector2dF& overscrollDelta, - const gfx::Vector2dF& accumulatedOverscroll, - const gfx::PointF& position, - const gfx::Vector2dF& velocity, - const cc::OverscrollBehavior& behavior) { - blink::mojom::DidOverscrollParamsPtr params = - blink::mojom::DidOverscrollParams::New( - accumulatedOverscroll, overscrollDelta, velocity, position, behavior); - - // If we're currently handling an event, stash the overscroll data such that - // it can be bundled in the event ack. - if (handling_input_state_) { - handling_input_state_->event_overscroll = std::move(params); - return; - } - - delegate_->OnDidOverscroll(std::move(params)); -} - -void RenderWidgetInputHandler::InjectGestureScrollEvent( - blink::WebGestureDevice device, - const gfx::Vector2dF& delta, - ui::ScrollGranularity granularity, - cc::ElementId scrollable_area_element_id, - WebInputEvent::Type injected_type) { - DCHECK(ui::IsGestureScroll(injected_type)); - // If we're currently handling an input event, cache the appropriate - // parameters so we can dispatch the events directly once blink finishes - // handling the event. - // Otherwise, queue the event on the main thread event queue. - // The latter may occur when scrollbar scrolls are injected due to - // autoscroll timer - i.e. not within the handling of a mouse event. - // We don't always just enqueue events, since events queued to the - // MainThreadEventQueue in the middle of dispatch (which we are) won't - // be dispatched until the next time the queue gets to run. The side effect - // of that would be an extra frame of latency if we're injecting a scroll - // during the handling of a rAF aligned input event, such as mouse move. - if (handling_input_state_) { - // Multiple gestures may be injected during the dispatch of a single - // input event (e.g. Begin/Update). Create a vector and append to the - // end of it - the gestures will subsequently be injected in order. - if (!handling_input_state_->injected_scroll_params) { - handling_input_state_->injected_scroll_params = - std::make_unique<std::vector<InjectScrollGestureParams>>(); - } - - InjectScrollGestureParams params{device, delta, granularity, - scrollable_area_element_id, injected_type}; - handling_input_state_->injected_scroll_params->push_back(params); - } else { - base::TimeTicks now = base::TimeTicks::Now(); - std::unique_ptr<WebGestureEvent> gesture_event = - WebGestureEvent::GenerateInjectedScrollGesture( - injected_type, now, device, gfx::PointF(0, 0), delta, granularity); - if (injected_type == WebInputEvent::Type::kGestureScrollBegin) { - gesture_event->data.scroll_begin.scrollable_area_element_id = - scrollable_area_element_id.GetStableId(); - } - - ui::LatencyInfo latency_info; - ui::WebScopedInputEvent web_scoped_gesture_event(gesture_event.release()); - // TODO(acomminos): If/when we add support for gesture event attribution on - // the impl thread, have the caller provide attribution. - blink::WebInputEventAttribution attribution; - - widget_->GetInputEventQueue()->HandleEvent( - std::move(web_scoped_gesture_event), latency_info, - DISPATCH_TYPE_NON_BLOCKING, - blink::mojom::InputEventResultState::kNotConsumed, attribution, - HandledEventCallback()); - } -} - -void RenderWidgetInputHandler::HandleInjectedScrollGestures( - std::vector<InjectScrollGestureParams> injected_scroll_params, - const WebInputEvent& input_event, - const ui::LatencyInfo& original_latency_info) { - DCHECK(injected_scroll_params.size()); - - base::TimeTicks original_timestamp; - bool found_original_component = original_latency_info.FindLatency( - ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, &original_timestamp); - DCHECK(found_original_component); - - gfx::PointF position = ui::PositionInWidgetFromInputEvent(input_event); - for (const InjectScrollGestureParams& params : injected_scroll_params) { - // Set up a new LatencyInfo for the injected scroll - this is the original - // LatencyInfo for the input event that was being handled when the scroll - // was injected. This new LatencyInfo will have a modified type, and an - // additional scroll update component. Also set up a SwapPromiseMonitor that - // will cause the LatencyInfo to be sent up with the compositor frame, if - // the GSU causes a commit. This allows end to end latency to be logged for - // the injected scroll, annotated with the correct type. - ui::LatencyInfo scrollbar_latency_info(original_latency_info); - - // Currently only scrollbar is supported - if this DCHECK hits due to a - // new type being injected, please modify the type passed to - // |set_source_event_type()|. - DCHECK(params.device == blink::WebGestureDevice::kScrollbar); - scrollbar_latency_info.set_source_event_type( - ui::SourceEventType::SCROLLBAR); - scrollbar_latency_info.AddLatencyNumber( - ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT); - - if (params.type == WebInputEvent::Type::kGestureScrollUpdate) { - if (input_event.GetType() != WebInputEvent::Type::kGestureScrollUpdate) { - scrollbar_latency_info.AddLatencyNumberWithTimestamp( - last_injected_gesture_was_begin_ - ? ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT - : ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, - original_timestamp); - } else { - // If we're injecting a GSU in response to a GSU (touch drags of the - // scrollbar thumb in Blink handles GSUs, and reverses them with - // injected GSUs), the LatencyInfo will already have the appropriate - // SCROLL_UPDATE component set. - DCHECK( - scrollbar_latency_info.FindLatency( - ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, - nullptr) || - scrollbar_latency_info.FindLatency( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, - nullptr)); - } - } - - std::unique_ptr<WebGestureEvent> gesture_event = - WebGestureEvent::GenerateInjectedScrollGesture( - params.type, input_event.TimeStamp(), params.device, position, - params.scroll_delta, params.granularity); - if (params.type == WebInputEvent::Type::kGestureScrollBegin) { - gesture_event->data.scroll_begin.scrollable_area_element_id = - params.scrollable_area_element_id.GetStableId(); - last_injected_gesture_was_begin_ = true; - } else { - last_injected_gesture_was_begin_ = false; - } - - { - cc::LatencyInfoSwapPromiseMonitor swap_promise_monitor( - &scrollbar_latency_info, - widget_->layer_tree_host()->GetSwapPromiseManager(), nullptr); - auto scoped_event_metrics_monitor = - widget_->layer_tree_host()->GetScopedEventMetricsMonitor( - cc::EventMetrics::Create(gesture_event->GetTypeAsUiEventType(), - gesture_event->TimeStamp(), - gesture_event->GetScrollInputType())); - widget_->GetWebWidget()->HandleInputEvent(blink::WebCoalescedInputEvent( - *gesture_event, scrollbar_latency_info)); - } - } -} - -bool RenderWidgetInputHandler::DidChangeCursor(const ui::Cursor& cursor) { - if (current_cursor_.has_value() && current_cursor_.value() == cursor) - return false; - current_cursor_ = cursor; - return true; -} - -bool RenderWidgetInputHandler::ProcessTouchAction( - cc::TouchAction touch_action) { - if (!handling_input_state_) - return false; - // Ignore setTouchAction calls that result from synthetic touch events (eg. - // when blink is emulating touch with mouse). - if (handling_input_state_->event_type != WebInputEvent::Type::kTouchStart) - return false; - - handling_input_state_->touch_action = touch_action; - return true; -} - -} // namespace content diff --git a/chromium/content/renderer/input/render_widget_input_handler.h b/chromium/content/renderer/input/render_widget_input_handler.h deleted file mode 100644 index 289cb9ccc0a..00000000000 --- a/chromium/content/renderer/input/render_widget_input_handler.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_H_ -#define CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/time/time.h" -#include "content/common/input/input_event_dispatch_type.h" -#include "content/renderer/input/main_thread_event_queue.h" -#include "third_party/blink/public/common/input/web_coalesced_input_event.h" -#include "third_party/blink/public/common/input/web_gesture_event.h" -#include "third_party/blink/public/web/web_hit_test_result.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/ui_base_types.h" -#include "ui/events/blink/did_overscroll_params.h" -#include "ui/events/types/scroll_types.h" - -namespace cc { -struct ElementId; -struct OverscrollBehavior; -} - -namespace ui { -class LatencyInfo; -} - -namespace viz { -class FrameSinkId; -} - -namespace content { - -class RenderWidget; -class RenderWidgetInputHandlerDelegate; - -// RenderWidgetInputHandler is an IPC-agnostic input handling class. -// IPC transport code should live in RenderWidget or RenderWidgetMusConnection. -class CONTENT_EXPORT RenderWidgetInputHandler { - public: - RenderWidgetInputHandler(RenderWidgetInputHandlerDelegate* delegate, - RenderWidget* widget); - virtual ~RenderWidgetInputHandler(); - - // Hit test the given point to find out the frame underneath and - // returns the FrameSinkId for that frame. |local_point| returns the point - // in the coordinate space of the FrameSinkId that was hit. - viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point, - gfx::PointF* local_point); - - // Handle input events from the input event provider. - virtual void HandleInputEvent( - const blink::WebCoalescedInputEvent& coalesced_event, - HandledEventCallback callback); - - // Handle overscroll from Blink. - void DidOverscrollFromBlink(const gfx::Vector2dF& overscrollDelta, - const gfx::Vector2dF& accumulatedOverscroll, - const gfx::PointF& position, - const gfx::Vector2dF& velocity, - const cc::OverscrollBehavior& behavior); - - void InjectGestureScrollEvent(blink::WebGestureDevice device, - const gfx::Vector2dF& delta, - ui::ScrollGranularity granularity, - cc::ElementId scrollable_area_element_id, - blink::WebInputEvent::Type injected_type); - - bool handling_input_event() const { return handling_input_event_; } - void set_handling_input_event(bool handling_input_event) { - handling_input_event_ = handling_input_event; - } - - // Process the touch action, returning whether the action should be relayed - // to the browser. - bool ProcessTouchAction(cc::TouchAction touch_action); - - // Process the new cursor and returns true if it has changed from the last - // cursor. - bool DidChangeCursor(const ui::Cursor& cursor); - - // Do a hit test for a given point in viewport coordinate. - blink::WebHitTestResult GetHitTestResultAtPoint(const gfx::PointF& point); - - private: - class HandlingState; - struct InjectScrollGestureParams { - blink::WebGestureDevice device; - gfx::Vector2dF scroll_delta; - ui::ScrollGranularity granularity; - cc::ElementId scrollable_area_element_id; - blink::WebInputEvent::Type type; - }; - - blink::WebInputEventResult HandleTouchEvent( - const blink::WebCoalescedInputEvent& coalesced_event); - - void HandleInjectedScrollGestures( - std::vector<InjectScrollGestureParams> injected_scroll_params, - const WebInputEvent& input_event, - const ui::LatencyInfo& original_latency_info); - - RenderWidgetInputHandlerDelegate* const delegate_; - - RenderWidget* const widget_; - - // Are we currently handling an input event? - bool handling_input_event_ = false; - - // Current state from HandleInputEvent. This variable is stack allocated - // and is not owned. - HandlingState* handling_input_state_ = nullptr; - - // We store the current cursor object so we can avoid spamming SetCursor - // messages. - base::Optional<ui::Cursor> current_cursor_; - - // Indicates if the next sequence of Char events should be suppressed or not. - bool suppress_next_char_events_ = false; - - // Whether the last injected scroll gesture was a GestureScrollBegin. Used to - // determine which GestureScrollUpdate is the first in a gesture sequence for - // latency classification. - bool last_injected_gesture_was_begin_ = false; - - base::WeakPtrFactory<RenderWidgetInputHandler> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(RenderWidgetInputHandler); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_H_ diff --git a/chromium/content/renderer/input/render_widget_input_handler_delegate.h b/chromium/content/renderer/input/render_widget_input_handler_delegate.h deleted file mode 100644 index 69686ad2cf4..00000000000 --- a/chromium/content/renderer/input/render_widget_input_handler_delegate.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_DELEGATE_H_ -#define CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_DELEGATE_H_ - -#include <memory> - -#include "content/common/content_export.h" -#include "third_party/blink/public/mojom/input/input_handler.mojom.h" -#include "third_party/blink/public/platform/web_input_event_result.h" - -namespace blink { -class WebGestureEvent; -class WebMouseEvent; -} - -namespace gfx { -class Vector2dF; -} - -namespace content { - -class RenderWidgetInputHandler; - -// Consumers of RenderWidgetInputHandler implement this delegate in order to -// transport input handling information across processes. -class CONTENT_EXPORT RenderWidgetInputHandlerDelegate { - public: - // Called when animations due to focus change have completed (if any). - virtual void FocusChangeComplete() = 0; - - // Called to forward a gesture event to the compositor thread, to effect - // the elastic overscroll effect. - virtual void ObserveGestureEventAndResult( - const blink::WebGestureEvent& gesture_event, - const gfx::Vector2dF& unused_delta, - const cc::OverscrollBehavior& overscroll_behavior, - bool event_processed) = 0; - - // Notifies that a key event was just handled. - virtual void OnDidHandleKeyEvent() = 0; - - // Notifies that an overscroll was completed from Blink. - virtual void OnDidOverscroll(blink::mojom::DidOverscrollParamsPtr params) = 0; - - // Notifies the delegate of the |input_handler| managing it. - virtual void SetInputHandler(RenderWidgetInputHandler* input_handler) = 0; - - // Call this if virtual keyboard should be displayed, e.g. after a tap on an - // input field on mobile. Note that we do this just by setting a bit in - // text input state and update it to the browser such that browser process can - // be up to date when showing virtual keyboard. - virtual void ShowVirtualKeyboard() = 0; - - // Send an update of text input state to the browser process. - virtual void UpdateTextInputState() = 0; - - // Clear the text input state. - virtual void ClearTextInputState() = 0; - - // Notifies that a gesture event is about to be handled. - // Returns true if no further handling is needed. In that case, the event - // won't be sent to WebKit. - virtual bool WillHandleGestureEvent(const blink::WebGestureEvent& event) = 0; - - // Notifies that a mouse event is about to be handled. - // Returns true if no further handling is needed. In that case, the event - // won't be sent to WebKit or trigger DidHandleMouseEvent(). - virtual bool WillHandleMouseEvent(const blink::WebMouseEvent& event) = 0; - - // Whether buffered touch events should be supported or not. - virtual bool SupportsBufferedTouchEvents() = 0; - - protected: - virtual ~RenderWidgetInputHandlerDelegate() = default; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_DELEGATE_H_ diff --git a/chromium/content/renderer/input/synchronous_compositor_proxy.cc b/chromium/content/renderer/input/synchronous_compositor_proxy.cc index d95fa790edb..97595a7bcc4 100644 --- a/chromium/content/renderer/input/synchronous_compositor_proxy.cc +++ b/chromium/content/renderer/input/synchronous_compositor_proxy.cc @@ -98,10 +98,10 @@ void SynchronousCompositorProxy::DidActivatePendingTree() { SendAsyncRendererStateIfNeeded(); } -mojom::SyncCompositorCommonRendererParamsPtr +blink::mojom::SyncCompositorCommonRendererParamsPtr SynchronousCompositorProxy::PopulateNewCommonParams() { - mojom::SyncCompositorCommonRendererParamsPtr params = - mojom::SyncCompositorCommonRendererParams::New(); + blink::mojom::SyncCompositorCommonRendererParamsPtr params = + blink::mojom::SyncCompositorCommonRendererParams::New(); params->version = ++version_; params->total_scroll_offset = total_scroll_offset_; params->max_scroll_offset = max_scroll_offset_; @@ -116,7 +116,7 @@ SynchronousCompositorProxy::PopulateNewCommonParams() { } void SynchronousCompositorProxy::DemandDrawHwAsync( - mojom::SyncCompositorDemandDrawHwParamsPtr params) { + blink::mojom::SyncCompositorDemandDrawHwParamsPtr params) { DemandDrawHw( std::move(params), base::BindOnce(&SynchronousCompositorProxy::SendDemandDrawHwAsyncReply, @@ -124,7 +124,7 @@ void SynchronousCompositorProxy::DemandDrawHwAsync( } void SynchronousCompositorProxy::DemandDrawHw( - mojom::SyncCompositorDemandDrawHwParamsPtr params, + blink::mojom::SyncCompositorDemandDrawHwParamsPtr params, DemandDrawHwCallback callback) { invalidate_needs_draw_ = false; hardware_draw_reply_ = std::move(callback); @@ -145,7 +145,9 @@ void SynchronousCompositorProxy::DemandDrawHw( } void SynchronousCompositorProxy::WillSkipDraw() { - layer_tree_frame_sink_->WillSkipDraw(); + if (layer_tree_frame_sink_) { + layer_tree_frame_sink_->WillSkipDraw(); + } } struct SynchronousCompositorProxy::SharedMemoryWithSize { @@ -173,7 +175,7 @@ void SynchronousCompositorProxy::ZeroSharedMemory() { } void SynchronousCompositorProxy::DemandDrawSw( - mojom::SyncCompositorDemandDrawSwParamsPtr params, + blink::mojom::SyncCompositorDemandDrawSwParamsPtr params, DemandDrawSwCallback callback) { invalidate_needs_draw_ = false; software_draw_reply_ = std::move(callback); @@ -198,7 +200,7 @@ void SynchronousCompositorProxy::DemandDrawSw( } void SynchronousCompositorProxy::DoDemandDrawSw( - mojom::SyncCompositorDemandDrawSwParamsPtr params) { + blink::mojom::SyncCompositorDemandDrawSwParamsPtr params) { DCHECK(layer_tree_frame_sink_); DCHECK(software_draw_shm_->zeroed); software_draw_shm_->zeroed = false; @@ -227,7 +229,7 @@ void SynchronousCompositorProxy::SubmitCompositorFrame( base::Optional<viz::HitTestRegionList> hit_test_region_list) { // Verify that exactly one of these is true. DCHECK(hardware_draw_reply_.is_null() ^ software_draw_reply_.is_null()); - mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params = + blink::mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params = PopulateNewCommonParams(); if (hardware_draw_reply_) { @@ -304,7 +306,7 @@ void SynchronousCompositorProxy::SetSharedMemory( base::WritableSharedMemoryRegion shm_region, SetSharedMemoryCallback callback) { bool success = false; - mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params; + blink::mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params; if (shm_region.IsValid()) { base::WritableSharedMemoryMapping shm_mapping = shm_region.Map(); if (shm_mapping.IsValid()) { @@ -315,7 +317,8 @@ void SynchronousCompositorProxy::SetSharedMemory( } } if (!common_renderer_params) { - common_renderer_params = mojom::SyncCompositorCommonRendererParams::New(); + common_renderer_params = + blink::mojom::SyncCompositorCommonRendererParams::New(); } std::move(callback).Run(success, std::move(common_renderer_params)); } @@ -333,7 +336,7 @@ uint32_t SynchronousCompositorProxy::NextMetadataVersion() { } void SynchronousCompositorProxy::SendDemandDrawHwAsyncReply( - mojom::SyncCompositorCommonRendererParamsPtr, + blink::mojom::SyncCompositorCommonRendererParamsPtr, uint32_t layer_tree_frame_sink_id, uint32_t metadata_version, base::Optional<viz::CompositorFrame> frame, @@ -343,7 +346,7 @@ void SynchronousCompositorProxy::SendDemandDrawHwAsyncReply( } void SynchronousCompositorProxy::SendBeginFrameResponse( - mojom::SyncCompositorCommonRendererParamsPtr param) { + blink::mojom::SyncCompositorCommonRendererParamsPtr param) { control_host_->BeginFrameResponse(std::move(param)); } @@ -361,9 +364,10 @@ void SynchronousCompositorProxy::LayerTreeFrameSinkCreated() { } void SynchronousCompositorProxy::BindChannel( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request) { // Reset bound mojo channels before rebinding new variants as the // associated RenderWidgetHost may be reused. diff --git a/chromium/content/renderer/input/synchronous_compositor_proxy.h b/chromium/content/renderer/input/synchronous_compositor_proxy.h index 703fb153e96..1841bdae369 100644 --- a/chromium/content/renderer/input/synchronous_compositor_proxy.h +++ b/chromium/content/renderer/input/synchronous_compositor_proxy.h @@ -13,12 +13,12 @@ #include "base/memory/writable_shared_memory_region.h" #include "base/optional.h" #include "components/viz/common/frame_timing_details_map.h" -#include "content/common/input/synchronous_compositor.mojom.h" -#include "content/renderer/android/synchronous_layer_tree_frame_sink.h" +#include "content/renderer/input/synchronous_layer_tree_frame_sink.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" +#include "third_party/blink/public/mojom/input/synchronous_compositor.mojom.h" #include "third_party/blink/public/platform/input/synchronous_input_handler_proxy.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_f.h" @@ -29,11 +29,9 @@ class CompositorFrame; namespace content { -class SynchronousLayerTreeFrameSink; - class SynchronousCompositorProxy : public blink::SynchronousInputHandler, public SynchronousLayerTreeFrameSinkClient, - public mojom::SynchronousCompositor { + public blink::mojom::SynchronousCompositor { public: SynchronousCompositorProxy( blink::SynchronousInputHandlerProxy* input_handler_proxy); @@ -41,9 +39,11 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, void Init(); void BindChannel( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> + host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request); // blink::SynchronousInputHandler overrides. @@ -67,16 +67,16 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, void SetLayerTreeFrameSink( SynchronousLayerTreeFrameSink* layer_tree_frame_sink); - mojom::SyncCompositorCommonRendererParamsPtr PopulateNewCommonParams(); + blink::mojom::SyncCompositorCommonRendererParamsPtr PopulateNewCommonParams(); - // mojom::SynchronousCompositor overrides. + // blink::mojom::SynchronousCompositor overrides. void DemandDrawHwAsync( - mojom::SyncCompositorDemandDrawHwParamsPtr draw_params) final; - void DemandDrawHw(mojom::SyncCompositorDemandDrawHwParamsPtr params, + blink::mojom::SyncCompositorDemandDrawHwParamsPtr draw_params) final; + void DemandDrawHw(blink::mojom::SyncCompositorDemandDrawHwParamsPtr params, DemandDrawHwCallback callback) final; void SetSharedMemory(base::WritableSharedMemoryRegion shm_region, SetSharedMemoryCallback callback) final; - void DemandDrawSw(mojom::SyncCompositorDemandDrawSwParamsPtr params, + void DemandDrawSw(blink::mojom::SyncCompositorDemandDrawSwParamsPtr params, DemandDrawSwCallback callback) final; void WillSkipDraw() final; void ZeroSharedMemory() final; @@ -93,9 +93,10 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, protected: void SendAsyncRendererStateIfNeeded(); void LayerTreeFrameSinkCreated(); - void SendBeginFrameResponse(mojom::SyncCompositorCommonRendererParamsPtr); + void SendBeginFrameResponse( + blink::mojom::SyncCompositorCommonRendererParamsPtr); void SendDemandDrawHwAsyncReply( - mojom::SyncCompositorCommonRendererParamsPtr, + blink::mojom::SyncCompositorCommonRendererParamsPtr, uint32_t layer_tree_frame_sink_id, uint32_t metadata_version, base::Optional<viz::CompositorFrame>, @@ -108,16 +109,16 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, bool begin_frame_paused_ = false; private: - void DoDemandDrawSw(mojom::SyncCompositorDemandDrawSwParamsPtr params); + void DoDemandDrawSw(blink::mojom::SyncCompositorDemandDrawSwParamsPtr params); uint32_t NextMetadataVersion(); void HostDisconnected(); struct SharedMemoryWithSize; blink::SynchronousInputHandlerProxy* const input_handler_proxy_; - mojo::Remote<mojom::SynchronousCompositorControlHost> control_host_; - mojo::AssociatedRemote<mojom::SynchronousCompositorHost> host_; - mojo::AssociatedReceiver<mojom::SynchronousCompositor> receiver_{this}; + mojo::Remote<blink::mojom::SynchronousCompositorControlHost> control_host_; + mojo::AssociatedRemote<blink::mojom::SynchronousCompositorHost> host_; + mojo::AssociatedReceiver<blink::mojom::SynchronousCompositor> receiver_{this}; const bool use_in_process_zero_copy_software_draw_; const bool viz_frame_submission_enabled_; diff --git a/chromium/content/renderer/input/synchronous_compositor_registry.h b/chromium/content/renderer/input/synchronous_compositor_registry.h index 5d57d4242c6..a476b28e036 100644 --- a/chromium/content/renderer/input/synchronous_compositor_registry.h +++ b/chromium/content/renderer/input/synchronous_compositor_registry.h @@ -5,16 +5,15 @@ #ifndef CONTENT_RENDERER_INPUT_SYNCHRONOUS_COMPOSITOR_REGISTRY_H_ #define CONTENT_RENDERER_INPUT_SYNCHRONOUS_COMPOSITOR_REGISTRY_H_ +#include "content/renderer/input/synchronous_layer_tree_frame_sink.h" + namespace content { -class SynchronousLayerTreeFrameSink; class SynchronousCompositorRegistry { public: virtual void RegisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) = 0; virtual void UnregisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) = 0; protected: diff --git a/chromium/content/renderer/input/synchronous_layer_tree_frame_sink.h b/chromium/content/renderer/input/synchronous_layer_tree_frame_sink.h new file mode 100644 index 00000000000..83d8ee558b0 --- /dev/null +++ b/chromium/content/renderer/input/synchronous_layer_tree_frame_sink.h @@ -0,0 +1,58 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_INPUT_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ +#define CONTENT_RENDERER_INPUT_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ + +#include "cc/trees/layer_tree_frame_sink.h" +#include "components/viz/common/frame_timing_details_map.h" +#include "components/viz/common/hit_test/hit_test_region_list.h" +#include "components/viz/common/quads/compositor_frame.h" + +namespace content { + +// This class represents the client interface for the frame sink +// created for the synchronous compositor. +class SynchronousLayerTreeFrameSinkClient { + public: + virtual void DidActivatePendingTree() = 0; + virtual void Invalidate(bool needs_draw) = 0; + virtual void SubmitCompositorFrame( + uint32_t layer_tree_frame_sink_id, + base::Optional<viz::CompositorFrame> frame, + base::Optional<viz::HitTestRegionList> hit_test_region_list) = 0; + virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0; + virtual void SinkDestroyed() = 0; + + protected: + virtual ~SynchronousLayerTreeFrameSinkClient() {} +}; + +// This class represents the interface for the frame sink for the synchronous +// compositor. +class SynchronousLayerTreeFrameSink : public cc::LayerTreeFrameSink { + public: + using cc::LayerTreeFrameSink::LayerTreeFrameSink; + + virtual void SetSyncClient( + SynchronousLayerTreeFrameSinkClient* compositor) = 0; + virtual void DidPresentCompositorFrame( + const viz::FrameTimingDetailsMap& timing_details) = 0; + virtual void BeginFrame(const viz::BeginFrameArgs& args) = 0; + virtual void SetBeginFrameSourcePaused(bool paused) = 0; + virtual void SetMemoryPolicy(size_t bytes_limit) = 0; + virtual void ReclaimResources( + uint32_t layer_tree_frame_sink_id, + const std::vector<viz::ReturnedResource>& resources) = 0; + virtual void DemandDrawHw( + const gfx::Size& viewport_size, + const gfx::Rect& viewport_rect_for_tile_priority, + const gfx::Transform& transform_for_tile_priority) = 0; + virtual void DemandDrawSw(SkCanvas* canvas) = 0; + virtual void WillSkipDraw() = 0; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_INPUT_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ diff --git a/chromium/content/renderer/input/widget_input_handler_impl.cc b/chromium/content/renderer/input/widget_input_handler_impl.cc index d27b93ea269..ce94586fade 100644 --- a/chromium/content/renderer/input/widget_input_handler_impl.cc +++ b/chromium/content/renderer/input/widget_input_handler_impl.cc @@ -8,17 +8,17 @@ #include "base/bind.h" #include "base/check.h" -#include "content/common/input/ime_text_span_conversions.h" #include "content/common/input_messages.h" #include "content/renderer/ime_event_guard.h" +#include "content/renderer/input/frame_input_handler_impl.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget.h" +#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/input/web_keyboard_event.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" -#include "third_party/blink/public/web/web_ime_text_span.h" #include "third_party/blink/public/web/web_local_frame.h" namespace content { @@ -49,21 +49,9 @@ WidgetInputHandlerImpl::WidgetInputHandlerImpl( WidgetInputHandlerImpl::~WidgetInputHandlerImpl() {} -void WidgetInputHandlerImpl::SetAssociatedReceiver( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner; - if (content::RenderThreadImpl::current()) { - blink::scheduler::WebThreadScheduler* scheduler = - content::RenderThreadImpl::current()->GetWebMainThreadScheduler(); - task_runner = scheduler->DeprecatedDefaultTaskRunner(); - } - associated_receiver_.Bind(std::move(receiver), std::move(task_runner)); - associated_receiver_.set_disconnect_handler( - base::BindOnce(&WidgetInputHandlerImpl::Release, base::Unretained(this))); -} - void WidgetInputHandlerImpl::SetReceiver( - mojo::PendingReceiver<mojom::WidgetInputHandler> interface_receiver) { + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> + interface_receiver) { scoped_refptr<base::SingleThreadTaskRunner> task_runner; if (content::RenderThreadImpl::current()) { blink::scheduler::WebThreadScheduler* scheduler = @@ -103,17 +91,16 @@ void WidgetInputHandlerImpl::ImeSetComposition( const gfx::Range& range, int32_t start, int32_t end) { - RunOnMainThread( - base::BindOnce(&RenderWidget::OnImeSetComposition, render_widget_, text, - ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans), - range, start, end)); + RunOnMainThread(base::BindOnce(&RenderWidget::OnImeSetComposition, + render_widget_, text, ime_text_spans, range, + start, end)); } static void ImeCommitTextOnMainThread( base::WeakPtr<RenderWidget> render_widget, scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner, const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position, WidgetInputHandlerImpl::ImeCommitTextCallback callback) { @@ -130,8 +117,7 @@ void WidgetInputHandlerImpl::ImeCommitText( ImeCommitTextCallback callback) { RunOnMainThread( base::BindOnce(&ImeCommitTextOnMainThread, render_widget_, - base::ThreadTaskRunnerHandle::Get(), text, - ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans), + base::ThreadTaskRunnerHandle::Get(), text, ime_text_spans, range, relative_cursor_position, std::move(callback))); } @@ -153,14 +139,14 @@ void WidgetInputHandlerImpl::RequestCompositionUpdates(bool immediate_request, } void WidgetInputHandlerImpl::DispatchEvent( - std::unique_ptr<content::InputEvent> event, + std::unique_ptr<blink::WebCoalescedInputEvent> event, DispatchEventCallback callback) { TRACE_EVENT0("input", "WidgetInputHandlerImpl::DispatchEvent"); input_handler_manager_->DispatchEvent(std::move(event), std::move(callback)); } void WidgetInputHandlerImpl::DispatchNonBlockingEvent( - std::unique_ptr<content::InputEvent> event) { + std::unique_ptr<blink::WebCoalescedInputEvent> event) { TRACE_EVENT0("input", "WidgetInputHandlerImpl::DispatchNonBlockingEvent"); input_handler_manager_->DispatchEvent(std::move(event), DispatchEventCallback()); @@ -187,14 +173,24 @@ void WidgetInputHandlerImpl::InputWasProcessed() { } void WidgetInputHandlerImpl::AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_receiver) { input_handler_manager_->AttachSynchronousCompositor( std::move(control_host), std::move(host), std::move(compositor_receiver)); } +void WidgetInputHandlerImpl::GetFrameWidgetInputHandler( + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler> + frame_receiver) { + mojo::MakeSelfOwnedAssociatedReceiver( + std::make_unique<FrameInputHandlerImpl>( + render_widget_, main_thread_task_runner_, input_event_queue_), + std::move(frame_receiver)); +} + void WidgetInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) { if (input_event_queue_) { input_event_queue_->QueueClosure(base::BindOnce( @@ -217,7 +213,6 @@ void WidgetInputHandlerImpl::Release() { if (!main_thread_task_runner_->BelongsToCurrentThread()) { // Close the binding on the compositor thread first before telling the main // thread to delete this object. - associated_receiver_.reset(); receiver_.reset(); main_thread_task_runner_->PostTask( FROM_HERE, base::BindOnce(&WidgetInputHandlerImpl::Release, diff --git a/chromium/content/renderer/input/widget_input_handler_impl.h b/chromium/content/renderer/input/widget_input_handler_impl.h index 86d288b5967..61d239d0bc0 100644 --- a/chromium/content/renderer/input/widget_input_handler_impl.h +++ b/chromium/content/renderer/input/widget_input_handler_impl.h @@ -7,9 +7,10 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" -#include "content/common/input/input_handler.mojom.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/common/input/web_coalesced_input_event.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" namespace content { class MainThreadEventQueue; @@ -20,7 +21,7 @@ class WidgetInputHandlerManager; // interface. If threaded compositing is used this thread will live on // the compositor thread and proxy events to the main thread. This // is done so that events stay in order relative to other events. -class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { +class WidgetInputHandlerImpl : public blink::mojom::WidgetInputHandler { public: WidgetInputHandlerImpl( scoped_refptr<WidgetInputHandlerManager> manager, @@ -30,10 +31,10 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { ~WidgetInputHandlerImpl() override; void SetAssociatedReceiver( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> + mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler> interface_receiver); - void SetReceiver( - mojo::PendingReceiver<mojom::WidgetInputHandler> interface_receiver); + void SetReceiver(mojo::PendingReceiver<blink::mojom::WidgetInputHandler> + interface_receiver); void SetFocus(bool focused) override; void MouseCaptureLost() override; @@ -54,15 +55,21 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { void RequestTextInputStateUpdate() override; void RequestCompositionUpdates(bool immediate_request, bool monitor_request) override; - void DispatchEvent(std::unique_ptr<content::InputEvent>, + void DispatchEvent(std::unique_ptr<blink::WebCoalescedInputEvent>, DispatchEventCallback callback) override; - void DispatchNonBlockingEvent(std::unique_ptr<content::InputEvent>) override; + void DispatchNonBlockingEvent( + std::unique_ptr<blink::WebCoalescedInputEvent>) override; void WaitForInputProcessed(WaitForInputProcessedCallback callback) override; void AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> + host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_receiver) override; + void GetFrameWidgetInputHandler( + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler> + interface_request) override; void InputWasProcessed(); private: @@ -80,9 +87,7 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { // killed before we actually fully process the input. WaitForInputProcessedCallback input_processed_ack_; - mojo::Receiver<mojom::WidgetInputHandler> receiver_{this}; - mojo::AssociatedReceiver<mojom::WidgetInputHandler> associated_receiver_{ - this}; + mojo::Receiver<blink::mojom::WidgetInputHandler> receiver_{this}; base::WeakPtrFactory<WidgetInputHandlerImpl> weak_ptr_factory_{this}; diff --git a/chromium/content/renderer/input/widget_input_handler_manager.cc b/chromium/content/renderer/input/widget_input_handler_manager.cc index 4c606edf453..1464a8835b2 100644 --- a/chromium/content/renderer/input/widget_input_handler_manager.cc +++ b/chromium/content/renderer/input/widget_input_handler_manager.cc @@ -10,6 +10,7 @@ #include "base/check_op.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" +#include "cc/base/features.h" #include "content/common/input_messages.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_impl.h" @@ -51,11 +52,12 @@ blink::mojom::DidOverscrollParamsPtr ToDidOverscrollParams( overscroll_params->overscroll_behavior); } -void CallCallback(mojom::WidgetInputHandler::DispatchEventCallback callback, - blink::mojom::InputEventResultState result_state, - const ui::LatencyInfo& latency_info, - blink::mojom::DidOverscrollParamsPtr overscroll_params, - base::Optional<cc::TouchAction> touch_action) { +void CallCallback( + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::InputEventResultState result_state, + const ui::LatencyInfo& latency_info, + blink::mojom::DidOverscrollParamsPtr overscroll_params, + base::Optional<cc::TouchAction> touch_action) { ui::LatencyInfo::TraceIntermediateFlowEvents( {latency_info}, ChromeLatencyInfo::STEP_HANDLED_INPUT_EVENT_IMPL); std::move(callback).Run( @@ -81,9 +83,11 @@ blink::mojom::InputEventResultState InputEventDispositionToAck( return blink::mojom::InputEventResultState::kSetNonBlocking; case blink::InputHandlerProxy::DID_HANDLE_SHOULD_BUBBLE: return blink::mojom::InputEventResultState::kConsumedShouldBubble; + case blink::InputHandlerProxy::REQUIRES_MAIN_THREAD_HIT_TEST: + default: + NOTREACHED(); + return blink::mojom::InputEventResultState::kUnknown; } - NOTREACHED(); - return blink::mojom::InputEventResultState::kUnknown; } } // namespace @@ -114,7 +118,6 @@ class SynchronousCompositorProxyRegistry SynchronousCompositorProxy* proxy() { return proxy_.get(); } void RegisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); DCHECK_EQ(nullptr, sink_); @@ -124,7 +127,6 @@ class SynchronousCompositorProxyRegistry } void UnregisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); DCHECK_EQ(layer_tree_frame_sink, sink_); @@ -198,37 +200,19 @@ void WidgetInputHandlerManager::InitInputHandler() { WidgetInputHandlerManager::~WidgetInputHandlerManager() = default; -void WidgetInputHandlerManager::AddAssociatedInterface( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { - if (compositor_task_runner_) { - associated_host_ = mojo::SharedRemote<mojom::WidgetInputHandlerHost>( - std::move(host), compositor_task_runner_); - // Mojo channel bound on compositor thread. - compositor_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&WidgetInputHandlerManager::BindAssociatedChannel, this, - std::move(receiver))); - } else { - associated_host_ = - mojo::SharedRemote<mojom::WidgetInputHandlerHost>(std::move(host)); - // Mojo channel bound on main thread. - BindAssociatedChannel(std::move(receiver)); - } -} - void WidgetInputHandlerManager::AddInterface( - mojo::PendingReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver, + mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) { if (compositor_task_runner_) { - host_ = mojo::SharedRemote<mojom::WidgetInputHandlerHost>( + host_ = mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost>( std::move(host), compositor_task_runner_); // Mojo channel bound on compositor thread. compositor_task_runner_->PostTask( FROM_HERE, base::BindOnce(&WidgetInputHandlerManager::BindChannel, this, std::move(receiver))); } else { - host_ = mojo::SharedRemote<mojom::WidgetInputHandlerHost>(std::move(host)); + host_ = mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost>( + std::move(host)); // Mojo channel bound on main thread. BindChannel(std::move(receiver)); } @@ -243,12 +227,11 @@ void WidgetInputHandlerManager::WillShutdown() { } void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( - ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, const blink::WebInputEventAttribution& attribution) { DCHECK(input_event_queue_); input_event_queue_->HandleEvent( - std::move(event), latency_info, DISPATCH_TYPE_NON_BLOCKING, + std::move(event), DISPATCH_TYPE_NON_BLOCKING, blink::mojom::InputEventResultState::kSetNonBlocking, attribution, HandledEventCallback()); } @@ -256,7 +239,11 @@ void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( void WidgetInputHandlerManager::FindScrollTargetOnMainThread( const gfx::PointF& point, ElementAtPointCallback callback) { + TRACE_EVENT2("input", + "WidgetInputHandlerManager::FindScrollTargetOnMainThread", + "point.x", point.x(), "point.y", point.y()); DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); + DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification)); uint64_t element_id = render_widget_->GetHitTestResultAtPoint(point).GetScrollableContainerId(); @@ -270,7 +257,7 @@ void WidgetInputHandlerManager::DidAnimateForInput() { } void WidgetInputHandlerManager::DidStartScrollingViewport() { - mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost(); + blink::mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost(); if (!host) return; host->DidStartScrollingViewport(); @@ -281,27 +268,28 @@ void WidgetInputHandlerManager::GenerateScrollBeginAndSendToMainThread( const blink::WebInputEventAttribution& attribution) { DCHECK_EQ(update_event.GetType(), blink::WebInputEvent::Type::kGestureScrollUpdate); - blink::WebGestureEvent scroll_begin = - ui::ScrollBeginFromScrollUpdate(update_event); + std::unique_ptr<blink::WebCoalescedInputEvent> event = + std::make_unique<blink::WebCoalescedInputEvent>( + ui::ScrollBeginFromScrollUpdate(update_event).Clone(), + ui::LatencyInfo()); - DispatchNonBlockingEventToMainThread(scroll_begin.Clone(), ui::LatencyInfo(), - attribution); + DispatchNonBlockingEventToMainThread(std::move(event), attribution); } -void WidgetInputHandlerManager::SetWhiteListedTouchAction( +void WidgetInputHandlerManager::SetAllowedTouchAction( cc::TouchAction touch_action, uint32_t unique_touch_event_id, blink::InputHandlerProxy::EventDisposition event_disposition) { - white_listed_touch_action_ = touch_action; + allowed_touch_action_ = touch_action; } void WidgetInputHandlerManager::ProcessTouchAction( cc::TouchAction touch_action) { - if (mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost()) + if (blink::mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost()) host->SetTouchActionFromMain(touch_action); } -mojom::WidgetInputHandlerHost* +blink::mojom::WidgetInputHandlerHost* WidgetInputHandlerManager::GetWidgetInputHandlerHost() { if (associated_host_) return associated_host_.get(); @@ -311,9 +299,10 @@ WidgetInputHandlerManager::GetWidgetInputHandlerHost() { } void WidgetInputHandlerManager::AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request) { #if defined(OS_ANDROID) DCHECK(synchronous_compositor_registry_); @@ -353,22 +342,11 @@ void WidgetInputHandlerManager::LogInputTimingUMA() { } void WidgetInputHandlerManager::DispatchEvent( - std::unique_ptr<content::InputEvent> event, - mojom::WidgetInputHandler::DispatchEventCallback callback) { - if (!event || !event->web_event) { - // Call |callback| if it was available indicating this event wasn't - // handled. - if (callback) { - std::move(callback).Run( - blink::mojom::InputEventResultSource::kMainThread, ui::LatencyInfo(), - blink::mojom::InputEventResultState::kNotConsumed, nullptr, nullptr); - } - return; - } - + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback) { bool event_is_move = - event->web_event->GetType() == WebInputEvent::Type::kMouseMove || - event->web_event->GetType() == WebInputEvent::Type::kPointerMove; + event->Event().GetType() == WebInputEvent::Type::kMouseMove || + event->Event().GetType() == WebInputEvent::Type::kPointerMove; if (!event_is_move) LogInputTimingUMA(); @@ -394,7 +372,7 @@ void WidgetInputHandlerManager::DispatchEvent( // platform timestamp in this process. Instead use the time that the event is // received as the event's timestamp. if (!base::TimeTicks::IsConsistentAcrossProcesses()) { - event->web_event->SetTimeStamp(base::TimeTicks::Now()); + event->EventPointer()->SetTimeStamp(base::TimeTicks::Now()); } if (uses_input_handler_) { @@ -417,14 +395,13 @@ void WidgetInputHandlerManager::DispatchEvent( // either ACK the event as handled to the browser or forward it to the main // thread. input_handler_proxy_->HandleInputEventWithLatencyInfo( - std::move(event->web_event), event->latency_info, + std::move(event), base::BindOnce( &WidgetInputHandlerManager::DidHandleInputEventSentToCompositor, this, std::move(callback))); } else { DCHECK(!input_handler_proxy_); - DispatchDirectlyToWidget(std::move(event->web_event), event->latency_info, - std::move(callback)); + DispatchDirectlyToWidget(std::move(event), std::move(callback)); } } @@ -473,15 +450,19 @@ static void WaitForInputProcessedFromMain( auto redraw_complete_callback = base::BindOnce( &WidgetInputHandlerManager::InputWasProcessed, manager->AsWeakPtr()); - // We consider all observable effects of an input gesture to be processed + // Since wheel-events can kick off animations, we can not consider + // all observable effects of an input gesture to be processed // when the CompositorFrame caused by that input has been produced, send, and - // displayed. RequestPresentation will force a a commit and redraw and - // callback when the CompositorFrame has been displayed in the display - // service. Some examples of non-trivial effects that require waiting that - // long: committing NonFastScrollRegions to the compositor, sending - // touch-action rects to the browser, and sending updated surface information - // to the display compositor for up-to-date OOPIF hit-testing. - render_widget->RequestPresentation(std::move(redraw_complete_callback)); + // displayed. Therefore, explicitly request the presentation *after* any + // ongoing scroll-animation ends. After the scroll-animation ends (if any), + // the call will force a commit and redraw and callback when the + // CompositorFrame has been displayed in the display service. Some examples of + // non-trivial effects that require waiting that long: committing + // NonFastScrollRegions to the compositor, sending touch-action rects to the + // browser, and sending updated surface information to the display compositor + // for up-to-date OOPIF hit-testing. + render_widget->RequestPresentationAfterScrollAnimationEnd( + std::move(redraw_complete_callback)); } void WidgetInputHandlerManager::WaitForInputProcessed( @@ -492,9 +473,9 @@ void WidgetInputHandlerManager::WaitForInputProcessed( input_processed_callback_ = std::move(callback); // We mustn't touch render_widget_ from the impl thread so post all the setup - // to the main thread. - main_thread_task_runner_->PostTask( - FROM_HERE, + // to the main thread. Make sure the callback runs after all the queued events + // are dispatched. + input_event_queue_->QueueClosure( base::BindOnce(&WaitForInputProcessedFromMain, render_widget_)); } @@ -549,20 +530,8 @@ void WidgetInputHandlerManager::InitOnInputHandlingThread( #endif } -void WidgetInputHandlerManager::BindAssociatedChannel( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver) { - if (!receiver.is_valid()) - return; - // Don't pass the |input_event_queue_| on if we don't have a - // |compositor_task_runner_| as events might get out of order. - WidgetInputHandlerImpl* handler = new WidgetInputHandlerImpl( - this, main_thread_task_runner_, - compositor_task_runner_ ? input_event_queue_ : nullptr, render_widget_); - handler->SetAssociatedReceiver(std::move(receiver)); -} - void WidgetInputHandlerManager::BindChannel( - mojo::PendingReceiver<mojom::WidgetInputHandler> receiver) { + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver) { if (!receiver.is_valid()) return; // Don't pass the |input_event_queue_| on if we don't have a @@ -574,9 +543,8 @@ void WidgetInputHandlerManager::BindChannel( } void WidgetInputHandlerManager::DispatchDirectlyToWidget( - const ui::WebScopedInputEvent& event, - const ui::LatencyInfo& latency, - mojom::WidgetInputHandler::DispatchEventCallback callback) { + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback) { // This path should only be taken by non-frame RenderWidgets that don't use a // compositor (e.g. popups, plugins). Events bounds for a frame RenderWidget // must be passed through the InputHandlerProxy first. @@ -586,9 +554,10 @@ void WidgetInputHandlerManager::DispatchDirectlyToWidget( // was just recreated for a provisional frame. if (!render_widget_ || render_widget_->IsForProvisionalFrame()) { if (callback) { - std::move(callback).Run( - blink::mojom::InputEventResultSource::kMainThread, latency, - blink::mojom::InputEventResultState::kNotConsumed, nullptr, nullptr); + std::move(callback).Run(blink::mojom::InputEventResultSource::kMainThread, + event->latency_info(), + blink::mojom::InputEventResultState::kNotConsumed, + nullptr, nullptr); } return; } @@ -597,15 +566,41 @@ void WidgetInputHandlerManager::DispatchDirectlyToWidget( base::BindOnce(&WidgetInputHandlerManager::DidHandleInputEventSentToMain, this, std::move(callback)); - blink::WebCoalescedInputEvent coalesced_event(*event, latency); - render_widget_->HandleInputEvent(coalesced_event, std::move(send_callback)); + render_widget_->HandleInputEvent(*event, std::move(send_callback)); +} + +void WidgetInputHandlerManager::FindScrollTargetReply( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback browser_callback, + uint64_t hit_test_result) { + TRACE_EVENT1("input", "WidgetInputHandlerManager::FindScrollTargetReply", + "hit_test_result", hit_test_result); + DCHECK(InputThreadTaskRunner()->BelongsToCurrentThread()); + DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification)); + + // If the input_handler was destroyed in the mean time just ACK the event as + // unconsumed to the browser and drop further handling. + if (!input_handler_proxy_) { + std::move(browser_callback) + .Run(blink::mojom::InputEventResultSource::kMainThread, + ui::LatencyInfo(), + blink::mojom::InputEventResultState::kNotConsumed, nullptr, + nullptr); + return; + } + + input_handler_proxy_->ContinueScrollBeginAfterMainThreadHitTest( + std::move(event), + base::BindOnce( + &WidgetInputHandlerManager::DidHandleInputEventSentToCompositor, this, + std::move(browser_callback)), + hit_test_result); } void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::InputHandlerProxy::EventDisposition event_disposition, - ui::WebScopedInputEvent input_event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams> overscroll_params, const blink::WebInputEventAttribution& attribution) { @@ -615,18 +610,47 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor( DCHECK(InputThreadTaskRunner()->BelongsToCurrentThread()); ui::LatencyInfo::TraceIntermediateFlowEvents( - {latency_info}, ChromeLatencyInfo::STEP_DID_HANDLE_INPUT_AND_OVERSCROLL); + {event->latency_info()}, + ChromeLatencyInfo::STEP_DID_HANDLE_INPUT_AND_OVERSCROLL); + + if (event_disposition == + blink::InputHandlerProxy::REQUIRES_MAIN_THREAD_HIT_TEST) { + TRACE_EVENT_INSTANT0("input", "PostingHitTestToMainThread", + TRACE_EVENT_SCOPE_THREAD); + // TODO(bokan): We're going to need to perform a hit test on the main thread + // before we can continue handling the event. This is the critical path of a + // scroll so we should probably ensure the scheduler can prioritize it + // accordingly. https://crbug.com/1082618. + DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification)); + DCHECK_EQ(event->Event().GetType(), + blink::WebInputEvent::Type::kGestureScrollBegin); + DCHECK(input_handler_proxy_); + + gfx::PointF event_position = + static_cast<const blink::WebGestureEvent&>(event->Event()) + .PositionInWidget(); + + ElementAtPointCallback result_callback = base::BindOnce( + &WidgetInputHandlerManager::FindScrollTargetReply, this->AsWeakPtr(), + std::move(event), std::move(callback)); + + main_thread_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&WidgetInputHandlerManager::FindScrollTargetOnMainThread, + this, event_position, std::move(result_callback))); + return; + } blink::mojom::InputEventResultState ack_state = InputEventDispositionToAck(event_disposition); if (ack_state == blink::mojom::InputEventResultState::kConsumed) { main_thread_scheduler_->DidHandleInputEventOnCompositorThread( - *input_event, blink::scheduler::WebThreadScheduler::InputEventState:: - EVENT_CONSUMED_BY_COMPOSITOR); + event->Event(), blink::scheduler::WebThreadScheduler::InputEventState:: + EVENT_CONSUMED_BY_COMPOSITOR); } else if (MainThreadEventQueue::IsForwardedAndSchedulerKnown(ack_state)) { main_thread_scheduler_->DidHandleInputEventOnCompositorThread( - *input_event, blink::scheduler::WebThreadScheduler::InputEventState:: - EVENT_FORWARDED_TO_MAIN_THREAD); + event->Event(), blink::scheduler::WebThreadScheduler::InputEventState:: + EVENT_FORWARDED_TO_MAIN_THREAD); } if (ack_state == blink::mojom::InputEventResultState::kSetNonBlocking || @@ -634,27 +658,27 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor( blink::mojom::InputEventResultState::kSetNonBlockingDueToFling || ack_state == blink::mojom::InputEventResultState::kNotConsumed) { DCHECK(!overscroll_params); - DCHECK(!latency_info.coalesced()); + DCHECK(!event->latency_info().coalesced()); InputEventDispatchType dispatch_type = callback.is_null() ? DISPATCH_TYPE_NON_BLOCKING : DISPATCH_TYPE_BLOCKING; HandledEventCallback handled_event = base::BindOnce( &WidgetInputHandlerManager::DidHandleInputEventSentToMain, this, std::move(callback)); - input_event_queue_->HandleEvent(std::move(input_event), latency_info, - dispatch_type, ack_state, attribution, - std::move(handled_event)); + input_event_queue_->HandleEvent(std::move(event), dispatch_type, ack_state, + attribution, std::move(handled_event)); return; } if (callback) { std::move(callback).Run( - blink::mojom::InputEventResultSource::kCompositorThread, latency_info, - ack_state, ToDidOverscrollParams(overscroll_params.get()), nullptr); + blink::mojom::InputEventResultSource::kCompositorThread, + event->latency_info(), ack_state, + ToDidOverscrollParams(overscroll_params.get()), nullptr); } } void WidgetInputHandlerManager::DidHandleInputEventSentToMain( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::mojom::InputEventResultState ack_state, const ui::LatencyInfo& latency_info, blink::mojom::DidOverscrollParamsPtr overscroll_params, @@ -669,10 +693,10 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToMain( {latency_info}, ChromeLatencyInfo::STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL); if (!touch_action.has_value()) { - TRACE_EVENT_INSTANT0("input", "Using white_listed_touch_action", + TRACE_EVENT_INSTANT0("input", "Using allowed_touch_action", TRACE_EVENT_SCOPE_THREAD); - touch_action = white_listed_touch_action_; - white_listed_touch_action_.reset(); + touch_action = allowed_touch_action_; + allowed_touch_action_.reset(); } // This method is called from either the main thread or the compositor thread. bool is_compositor_thread = compositor_task_runner_ && diff --git a/chromium/content/renderer/input/widget_input_handler_manager.h b/chromium/content/renderer/input/widget_input_handler_manager.h index d5d95972da8..18bed414154 100644 --- a/chromium/content/renderer/input/widget_input_handler_manager.h +++ b/chromium/content/renderer/input/widget_input_handler_manager.h @@ -9,11 +9,11 @@ #include "base/single_thread_task_runner.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "content/common/input/input_handler.mojom.h" #include "content/renderer/render_frame_impl.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" #include "third_party/blink/public/platform/input/input_handler_proxy.h" #include "third_party/blink/public/platform/input/input_handler_proxy_client.h" @@ -67,18 +67,15 @@ class CONTENT_EXPORT WidgetInputHandlerManager final scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, blink::scheduler::WebThreadScheduler* main_thread_scheduler, bool needs_input_handler); - void AddAssociatedInterface( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host); - void AddInterface(mojo::PendingReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host); + void AddInterface( + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver, + mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host); // InputHandlerProxyClient overrides. void WillShutdown() override; void DispatchNonBlockingEventToMainThread( - ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, const blink::WebInputEventAttribution& attribution) override; void DidAnimateForInput() override; @@ -86,7 +83,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager final void GenerateScrollBeginAndSendToMainThread( const blink::WebGestureEvent& update_event, const blink::WebInputEventAttribution& attribution) override; - void SetWhiteListedTouchAction( + void SetAllowedTouchAction( cc::TouchAction touch_action, uint32_t unique_touch_event_id, blink::InputHandlerProxy::EventDisposition event_disposition) override; @@ -95,17 +92,20 @@ class CONTENT_EXPORT WidgetInputHandlerManager final const blink::WebGestureEvent& gesture_event, const cc::InputHandlerScrollResult& scroll_result); - void DispatchEvent(std::unique_ptr<content::InputEvent> event, - mojom::WidgetInputHandler::DispatchEventCallback callback); + void DispatchEvent( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback); void ProcessTouchAction(cc::TouchAction touch_action); - mojom::WidgetInputHandlerHost* GetWidgetInputHandlerHost(); + blink::mojom::WidgetInputHandlerHost* GetWidgetInputHandlerHost(); void AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> + host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request); #if defined(OS_ANDROID) @@ -153,9 +153,8 @@ class CONTENT_EXPORT WidgetInputHandlerManager final void InitOnInputHandlingThread( const base::WeakPtr<cc::InputHandler>& input_handler, bool sync_compositing); - void BindAssociatedChannel( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver); - void BindChannel(mojo::PendingReceiver<mojom::WidgetInputHandler> receiver); + void BindChannel( + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver); // This method skips the input handler proxy and sends the event directly to // the RenderWidget (main thread). Should only be used by non-frame @@ -164,9 +163,15 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // InputHandlerProxy by calling DispatchEvent which will re-route to the main // thread if needed. void DispatchDirectlyToWidget( - const ui::WebScopedInputEvent& event, - const ui::LatencyInfo& latency, - mojom::WidgetInputHandler::DispatchEventCallback callback); + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback); + + // Used to return a result from FindScrollTargetOnMainThread. Will be called + // on the input handling thread. + void FindScrollTargetReply( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback browser_callback, + uint64_t hit_test_result); // This method is the callback used by the compositor input handler to // communicate back whether the event was successfully handled on the @@ -176,10 +181,9 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // on the input handling thread (i.e. if a compositor thread exists, it'll be // called from it). void DidHandleInputEventSentToCompositor( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::InputHandlerProxy::EventDisposition event_disposition, - ui::WebScopedInputEvent input_event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams> overscroll_params, const blink::WebInputEventAttribution& attribution); @@ -189,7 +193,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // called on either thread as non-blocking events sent to the main thread // will be ACKed immediately when added to the main thread event queue. void DidHandleInputEventSentToMain( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::mojom::InputEventResultState ack_state, const ui::LatencyInfo& latency_info, blink::mojom::DidOverscrollParamsPtr overscroll_params, @@ -216,18 +220,18 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // The WidgetInputHandlerHost is bound on the compositor task runner // but class can be called on the compositor and main thread. - mojo::SharedRemote<mojom::WidgetInputHandlerHost> host_; + mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost> host_; // Host that was passed as part of the FrameInputHandler associated // channel. - mojo::SharedRemote<mojom::WidgetInputHandlerHost> associated_host_; + mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost> associated_host_; // Any thread can access these variables. scoped_refptr<MainThreadEventQueue> input_event_queue_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - base::Optional<cc::TouchAction> white_listed_touch_action_; + base::Optional<cc::TouchAction> allowed_touch_action_; // Callback used to respond to the WaitForInputProcessed Mojo message. This // callback is set from and must be invoked from the Mojo-bound thread (i.e. diff --git a/chromium/content/renderer/loader/resource_dispatcher.cc b/chromium/content/renderer/loader/resource_dispatcher.cc index 4f6b3a9ce1c..70b959ead57 100644 --- a/chromium/content/renderer/loader/resource_dispatcher.cc +++ b/chromium/content/renderer/loader/resource_dispatcher.cc @@ -407,6 +407,11 @@ void ResourceDispatcher::OnTransferSizeUpdated(int request_id, transfer_size_diff); } +void ResourceDispatcher::SetCorsExemptHeaderList( + const std::vector<std::string>& list) { + cors_exempt_header_list_ = list; +} + ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( std::unique_ptr<RequestPeer> peer, network::mojom::RequestDestination request_destination, @@ -460,14 +465,14 @@ void ResourceDispatcher::StartSync( base::ThreadPool::CreateSingleThreadTaskRunner({}); task_runner->PostTask( FROM_HERE, - base::BindOnce(&SyncLoadContext::StartAsyncWithWaitableEvent, - std::move(request), routing_id, task_runner, - traffic_annotation, loader_options, - std::move(pending_factory), std::move(throttles), - base::Unretained(response), - base::Unretained(&redirect_or_response_event), - base::Unretained(terminate_sync_load_event_), timeout, - std::move(download_to_blob_registry))); + base::BindOnce( + &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request), + routing_id, task_runner, traffic_annotation, loader_options, + std::move(pending_factory), std::move(throttles), + base::Unretained(response), + base::Unretained(&redirect_or_response_event), + base::Unretained(terminate_sync_load_event_), timeout, + std::move(download_to_blob_registry), cors_exempt_header_list_)); // redirect_or_response_event will signal when each redirect completes, and // when the final response is complete. @@ -561,7 +566,8 @@ int ResourceDispatcher::StartAsync( blink::ThrottlingURLLoader::CreateLoaderAndStart( std::move(url_loader_factory), std::move(throttles), routing_id, request_id, loader_options, request.get(), client.get(), - traffic_annotation, std::move(loading_task_runner)); + traffic_annotation, std::move(loading_task_runner), + base::make_optional(cors_exempt_header_list_)); pending_request->url_loader = std::move(url_loader); pending_request->url_loader_client = std::move(client); @@ -603,6 +609,9 @@ void ResourceDispatcher::ToLocalURLResponseHead( RemoteToLocalTimeTicks(converter, &load_timing->push_end); RemoteToLocalTimeTicks(converter, &load_timing->service_worker_start_time); RemoteToLocalTimeTicks(converter, &load_timing->service_worker_ready_time); + RemoteToLocalTimeTicks(converter, &load_timing->service_worker_fetch_start); + RemoteToLocalTimeTicks(converter, + &load_timing->service_worker_respond_with_settled); } // TODO(dgozman): this is not used for navigation anymore, only for worker diff --git a/chromium/content/renderer/loader/resource_dispatcher.h b/chromium/content/renderer/loader/resource_dispatcher.h index 949cc1ecdfa..6b291710183 100644 --- a/chromium/content/renderer/loader/resource_dispatcher.h +++ b/chromium/content/renderer/loader/resource_dispatcher.h @@ -14,7 +14,6 @@ #include <string> #include <vector> -#include "base/containers/circular_deque.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -159,6 +158,13 @@ class CONTENT_EXPORT ResourceDispatcher { void OnTransferSizeUpdated(int request_id, int32_t transfer_size_diff); + // Sets the CORS exempt header list for sanity checking. + void SetCorsExemptHeaderList(const std::vector<std::string>& list); + + std::vector<std::string> cors_exempt_header_list() const { + return cors_exempt_header_list_; + } + // This is used only when |this| is created for a worker thread. // Sets |terminate_sync_load_event_| which will be signaled from the main // thread when the worker thread is being terminated so that the sync requests @@ -253,6 +259,8 @@ class CONTENT_EXPORT ResourceDispatcher { base::WaitableEvent* terminate_sync_load_event_ = nullptr; + std::vector<std::string> cors_exempt_header_list_; + base::WeakPtrFactory<ResourceDispatcher> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ResourceDispatcher); diff --git a/chromium/content/renderer/loader/sync_load_context.cc b/chromium/content/renderer/loader/sync_load_context.cc index ba16da6106d..b246fe3e65b 100644 --- a/chromium/content/renderer/loader/sync_load_context.cc +++ b/chromium/content/renderer/loader/sync_load_context.cc @@ -101,11 +101,13 @@ void SyncLoadContext::StartAsyncWithWaitableEvent( base::WaitableEvent* redirect_or_response_event, base::WaitableEvent* abort_event, base::TimeDelta timeout, - mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry) { - auto* context = new SyncLoadContext( - request.get(), std::move(pending_url_loader_factory), response, - redirect_or_response_event, abort_event, timeout, - std::move(download_to_blob_registry), loading_task_runner); + mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, + const std::vector<std::string>& cors_exempt_header_list) { + auto* context = + new SyncLoadContext(request.get(), std::move(pending_url_loader_factory), + response, redirect_or_response_event, abort_event, + timeout, std::move(download_to_blob_registry), + loading_task_runner, cors_exempt_header_list); context->request_id_ = context->resource_dispatcher_->StartAsync( std::move(request), routing_id, std::move(loading_task_runner), traffic_annotation, loader_options, base::WrapUnique(context), @@ -121,7 +123,8 @@ SyncLoadContext::SyncLoadContext( base::WaitableEvent* abort_event, base::TimeDelta timeout, mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + const std::vector<std::string>& cors_exempt_header_list) : response_(response), body_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), download_to_blob_registry_(std::move(download_to_blob_registry)), @@ -138,6 +141,7 @@ SyncLoadContext::SyncLoadContext( // Constructs a new ResourceDispatcher specifically for this request. resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); + resource_dispatcher_->SetCorsExemptHeaderList(cors_exempt_header_list); // Initialize the final URL with the original request URL. It will be // overwritten on redirects. diff --git a/chromium/content/renderer/loader/sync_load_context.h b/chromium/content/renderer/loader/sync_load_context.h index f7565e5dab0..9ba341f04af 100644 --- a/chromium/content/renderer/loader/sync_load_context.h +++ b/chromium/content/renderer/loader/sync_load_context.h @@ -66,8 +66,8 @@ class CONTENT_EXPORT SyncLoadContext : public RequestPeer { base::WaitableEvent* completed_event, base::WaitableEvent* abort_event, base::TimeDelta timeout, - mojo::PendingRemote<blink::mojom::BlobRegistry> - download_to_blob_registry); + mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, + const std::vector<std::string>& cors_exempt_header_list); ~SyncLoadContext() override; @@ -86,7 +86,8 @@ class CONTENT_EXPORT SyncLoadContext : public RequestPeer { base::WaitableEvent* abort_event, base::TimeDelta timeout, mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + const std::vector<std::string>& cors_exempt_header_list); // RequestPeer implementation: void OnUploadProgress(uint64_t position, uint64_t size) override; bool OnReceivedRedirect(const net::RedirectInfo& redirect_info, diff --git a/chromium/content/renderer/loader/sync_load_context_unittest.cc b/chromium/content/renderer/loader/sync_load_context_unittest.cc index d4d012d1ac3..3e30786489b 100644 --- a/chromium/content/renderer/loader/sync_load_context_unittest.cc +++ b/chromium/content/renderer/loader/sync_load_context_unittest.cc @@ -104,16 +104,17 @@ class SyncLoadContextTest : public testing::Test { base::WaitableEvent* redirect_or_response_event) { loading_thread_.task_runner()->PostTask( FROM_HERE, - base::BindOnce(&SyncLoadContext::StartAsyncWithWaitableEvent, - std::move(request), MSG_ROUTING_NONE, - loading_thread_.task_runner(), - TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */, - std::move(pending_factory), - std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(), - out_response, redirect_or_response_event, - nullptr /* terminate_sync_load_event */, - base::TimeDelta::FromSeconds(60) /* timeout */, - mojo::NullRemote() /* download_to_blob_registry */)); + base::BindOnce( + &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request), + MSG_ROUTING_NONE, loading_thread_.task_runner(), + TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */, + std::move(pending_factory), + std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(), + out_response, redirect_or_response_event, + nullptr /* terminate_sync_load_event */, + base::TimeDelta::FromSeconds(60) /* timeout */, + mojo::NullRemote() /* download_to_blob_registry */, + std::vector<std::string>() /* cors_exempt_header_list */)); } static void RunSyncLoadContextViaDataPipe( @@ -128,7 +129,8 @@ class SyncLoadContextTest : public testing::Test { response, redirect_or_response_event, nullptr /* terminate_sync_load_event */, base::TimeDelta::FromSeconds(60) /* timeout */, - mojo::NullRemote() /* download_to_blob_registry */, task_runner); + mojo::NullRemote() /* download_to_blob_registry */, task_runner, + std::vector<std::string>() /* cors_exempt_header_list */); // Override |resource_dispatcher_| for testing. auto dispatcher = std::make_unique<MockResourceDispatcher>(); diff --git a/chromium/content/renderer/loader/web_url_loader_impl.cc b/chromium/content/renderer/loader/web_url_loader_impl.cc index a506772220c..d571a441bfd 100644 --- a/chromium/content/renderer/loader/web_url_loader_impl.cc +++ b/chromium/content/renderer/loader/web_url_loader_impl.cc @@ -118,9 +118,11 @@ network::mojom::LoadTimingInfo ToMojoLoadTiming( load_timing.proxy_resolve_start, load_timing.proxy_resolve_end, load_timing.connect_timing, load_timing.send_start, load_timing.send_end, load_timing.receive_headers_start, load_timing.receive_headers_end, - load_timing.push_start, load_timing.push_end, - load_timing.service_worker_start_time, - load_timing.service_worker_ready_time); + load_timing.first_early_hints_time, load_timing.push_start, + load_timing.push_end, load_timing.service_worker_start_time, + load_timing.service_worker_ready_time, + load_timing.service_worker_fetch_start, + load_timing.service_worker_respond_with_settled); } // This is complementary to ConvertNetPriorityToWebKitPriority, defined in @@ -927,12 +929,14 @@ void WebURLLoaderImpl::PopulateURLResponse( response->SetConnectionReused(head.load_timing.socket_reused); response->SetWasFetchedViaSPDY(head.was_fetched_via_spdy); response->SetWasFetchedViaServiceWorker(head.was_fetched_via_service_worker); + response->SetServiceWorkerResponseSource(head.service_worker_response_source); response->SetWasFallbackRequiredByServiceWorker( head.was_fallback_required_by_service_worker); response->SetType(head.response_type); response->SetUrlListViaServiceWorker(head.url_list_via_service_worker); response->SetCacheStorageCacheName( - head.is_in_cache_storage + head.service_worker_response_source == + network::mojom::FetchResponseSource::kCacheStorage ? blink::WebString::FromUTF8(head.cache_storage_cache_name) : blink::WebString()); blink::WebVector<blink::WebString> cors_exposed_header_names( @@ -1112,7 +1116,7 @@ void WebURLLoaderImpl::LoadSynchronously( WebString::FromLatin1(sync_load_response.downloaded_blob->uuid), WebString::FromLatin1(sync_load_response.downloaded_blob->content_type), sync_load_response.downloaded_blob->size, - sync_load_response.downloaded_blob->blob.PassPipe()); + std::move(sync_load_response.downloaded_blob->blob)); } data.Assign(sync_load_response.data.data(), sync_load_response.data.size()); diff --git a/chromium/content/renderer/loader/web_url_request_util.cc b/chromium/content/renderer/loader/web_url_request_util.cc index 3c58401723c..e351493f1c9 100644 --- a/chromium/content/renderer/loader/web_url_request_util.cc +++ b/chromium/content/renderer/loader/web_url_request_util.cc @@ -149,7 +149,7 @@ WebHTTPBody GetWebHTTPBodyForRequestBody( http_body.AppendBlob(WebString::FromASCII(element.blob_uuid())); break; case network::mojom::DataElementType::kDataPipe: { - http_body.AppendDataPipe(element.CloneDataPipeGetter().PassPipe()); + http_body.AppendDataPipe(element.CloneDataPipeGetter()); break; } case network::mojom::DataElementType::kUnknown: @@ -203,11 +203,10 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody( } break; case WebHTTPBody::Element::kTypeBlob: { - DCHECK(element.optional_blob_handle.is_valid()); + DCHECK(element.optional_blob); mojo::Remote<blink::mojom::Blob> blob_remote( mojo::PendingRemote<blink::mojom::Blob>( - std::move(element.optional_blob_handle), - blink::mojom::Blob::Version_)); + std::move(element.optional_blob))); mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter_remote; @@ -222,7 +221,7 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody( // mojo::Remote<network::mojom::DataPipeGetter> data_pipe_getter. mojo::Remote<network::mojom::DataPipeGetter> data_pipe_getter( mojo::PendingRemote<network::mojom::DataPipeGetter>( - std::move(element.data_pipe_getter), 0u)); + std::move(element.data_pipe_getter))); // Set the cloned DataPipeGetter to the output |request_body|, while // keeping the original message pipe back in the input |httpBody|. This @@ -231,7 +230,7 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody( mojo::PendingRemote<network::mojom::DataPipeGetter> cloned_getter; data_pipe_getter->Clone(cloned_getter.InitWithNewPipeAndPassReceiver()); request_body->AppendDataPipe(std::move(cloned_getter)); - element.data_pipe_getter = data_pipe_getter.Unbind().PassPipe(); + element.data_pipe_getter = data_pipe_getter.Unbind(); break; } } diff --git a/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc index 5e7b8b3b7e8..505f87fef07 100644 --- a/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc +++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc @@ -171,7 +171,8 @@ scoped_refptr<WebWorkerFetchContextImpl> WebWorkerFetchContextImpl::Create( std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> - pending_subresource_loader_updater) { + pending_subresource_loader_updater, + const std::vector<std::string>& cors_exempt_header_list) { mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient> service_worker_client_receiver; mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry> @@ -209,7 +210,8 @@ scoped_refptr<WebWorkerFetchContextImpl> WebWorkerFetchContextImpl::Create( ->renderer() ->CreateWebSocketHandshakeThrottleProvider(), ChildThreadImpl::current()->thread_safe_sender(), - ChildThreadImpl::current()->child_process_host())); + ChildThreadImpl::current()->child_process_host(), + cors_exempt_header_list)); if (provider_context) { worker_fetch_context->set_controller_service_worker_mode( provider_context->GetControllerServiceWorkerMode()); @@ -241,7 +243,8 @@ WebWorkerFetchContextImpl::WebWorkerFetchContextImpl( std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider, ThreadSafeSender* thread_safe_sender, - mojo::SharedRemote<mojom::ChildProcessHost> process_host) + mojo::SharedRemote<mojom::ChildProcessHost> process_host, + const std::vector<std::string>& cors_exempt_header_list) : service_worker_client_receiver_( std::move(service_worker_client_receiver)), pending_service_worker_worker_client_registry_( @@ -259,7 +262,8 @@ WebWorkerFetchContextImpl::WebWorkerFetchContextImpl( throttle_provider_(std::move(throttle_provider)), websocket_handshake_throttle_provider_( std::move(websocket_handshake_throttle_provider)), - process_host_(std::move(process_host)) {} + process_host_(std::move(process_host)), + cors_exempt_header_list_(cors_exempt_header_list) {} WebWorkerFetchContextImpl::~WebWorkerFetchContextImpl() {} @@ -373,6 +377,7 @@ void WebWorkerFetchContextImpl::InitializeOnWorkerThread( DCHECK(!receiver_.is_bound()); DCHECK(!preference_watcher_receiver_.is_bound()); resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); + resource_dispatcher_->SetCorsExemptHeaderList(cors_exempt_header_list_); resource_dispatcher_->set_terminate_sync_load_event( terminate_sync_load_event_); @@ -424,13 +429,12 @@ blink::WebURLLoaderFactory* WebWorkerFetchContextImpl::GetURLLoaderFactory() { std::unique_ptr<blink::WebURLLoaderFactory> WebWorkerFetchContextImpl::WrapURLLoaderFactory( - mojo::ScopedMessagePipeHandle url_loader_factory_handle) { + blink::CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase> + url_loader_factory) { return std::make_unique<WebURLLoaderFactoryImpl>( resource_dispatcher_->GetWeakPtr(), base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( - mojo::PendingRemote<network::mojom::URLLoaderFactory>( - std::move(url_loader_factory_handle), - network::mojom::URLLoaderFactory::Version_))); + std::move(url_loader_factory))); } std::unique_ptr<blink::CodeCacheLoader> @@ -534,7 +538,8 @@ WebWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle( ancestor_frame_id_, std::move(task_runner)); } -mojo::ScopedMessagePipeHandle +blink::CrossVariantMojoReceiver< + blink::mojom::WorkerTimingContainerInterfaceBase> WebWorkerFetchContextImpl::TakePendingWorkerTimingReceiver(int request_id) { auto iter = worker_timing_container_receivers_.find(request_id); if (iter == worker_timing_container_receivers_.end()) { @@ -542,7 +547,7 @@ WebWorkerFetchContextImpl::TakePendingWorkerTimingReceiver(int request_id) { } auto receiver = std::move(iter->second); worker_timing_container_receivers_.erase(iter); - return receiver.PassPipe(); + return std::move(receiver); } void WebWorkerFetchContextImpl::SetIsOfflineMode(bool is_offline_mode) { @@ -620,7 +625,7 @@ WebWorkerFetchContextImpl::CloneForNestedWorkerInternal( ? websocket_handshake_throttle_provider_->Clone( std::move(task_runner)) : nullptr, - thread_safe_sender_.get(), process_host_)); + thread_safe_sender_.get(), process_host_, cors_exempt_header_list_)); new_context->is_on_sub_frame_ = is_on_sub_frame_; new_context->ancestor_frame_id_ = ancestor_frame_id_; new_context->frame_request_blocker_ = frame_request_blocker_; diff --git a/chromium/content/renderer/loader/web_worker_fetch_context_impl.h b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h index 6d08e2d5be3..8a45725b471 100644 --- a/chromium/content/renderer/loader/web_worker_fetch_context_impl.h +++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h @@ -85,7 +85,8 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> - pending_subresource_loader_updater); + pending_subresource_loader_updater, + const std::vector<std::string>& cors_exempt_header_list); // Clones this fetch context for a nested worker. // For non-PlzDedicatedWorker. This will be removed once PlzDedicatedWorker is @@ -110,7 +111,9 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl void InitializeOnWorkerThread(blink::AcceptLanguagesWatcher*) override; blink::WebURLLoaderFactory* GetURLLoaderFactory() override; std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory( - mojo::ScopedMessagePipeHandle url_loader_factory_handle) override; + blink::CrossVariantMojoRemote< + network::mojom::URLLoaderFactoryInterfaceBase> url_loader_factory) + override; std::unique_ptr<blink::CodeCacheLoader> CreateCodeCacheLoader() override; void WillSendRequest(blink::WebURLRequest&) override; blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode() @@ -130,8 +133,9 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl std::unique_ptr<blink::WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle( scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; - mojo::ScopedMessagePipeHandle TakePendingWorkerTimingReceiver( - int request_id) override; + blink::CrossVariantMojoReceiver< + blink::mojom::WorkerTimingContainerInterfaceBase> + TakePendingWorkerTimingReceiver(int request_id) override; void SetIsOfflineMode(bool is_offline_mode) override; // blink::mojom::ServiceWorkerWorkerClient implementation: @@ -215,7 +219,8 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider, ThreadSafeSender* thread_safe_sender, - mojo::SharedRemote<mojom::ChildProcessHost> process_host); + mojo::SharedRemote<mojom::ChildProcessHost> process_host, + const std::vector<std::string>& cors_exempt_header_list); ~WebWorkerFetchContextImpl() override; @@ -359,6 +364,8 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl mojo::SharedRemote<mojom::ChildProcessHost> process_host_; + std::vector<std::string> cors_exempt_header_list_; + std::unique_ptr<NavigationResponseOverrideParameters> response_override_; blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr; diff --git a/chromium/content/renderer/low_memory_mode_controller.cc b/chromium/content/renderer/low_memory_mode_controller.cc deleted file mode 100644 index a3e6fc43fb5..00000000000 --- a/chromium/content/renderer/low_memory_mode_controller.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/low_memory_mode_controller.h" - -#include "base/metrics/histogram_macros.h" -#include "third_party/blink/public/web/blink.h" -#include "v8/include/v8.h" - -namespace content { - -LowMemoryModeController::LowMemoryModeController() = default; - -LowMemoryModeController::~LowMemoryModeController() = default; - -void LowMemoryModeController::OnFrameCreated(bool is_main_frame) { - if (is_main_frame) { - // If the process is gaining its first main frame, disable memory - // savings mode. - if (++main_frame_count_ == 1) { - Disable(); - } - } else if (main_frame_count_ == 0) { - // The process is getting a new frame and none is main, enable - // memory savings mode (if not already on). - Enable(); - } -} - -void LowMemoryModeController::OnFrameDestroyed(bool is_main_frame) { - // If the process is losing its last main frame, enable memory - // savings mode. - if (is_main_frame && --main_frame_count_ == 0) { - Enable(); - } -} - -void LowMemoryModeController::Enable() { - if (is_enabled_) - return; - - blink::MainThreadIsolate()->EnableMemorySavingsMode(); - RecordHistogram(true); - is_enabled_ = true; -} - -void LowMemoryModeController::Disable() { - if (!is_enabled_) - return; - - blink::MainThreadIsolate()->DisableMemorySavingsMode(); - RecordHistogram(false); - is_enabled_ = false; -} - -void LowMemoryModeController::RecordHistogram(bool enabled) { - UMA_HISTOGRAM_BOOLEAN("SiteIsolation.LowMemoryMode.Transition", enabled); -} - -} // namespace content diff --git a/chromium/content/renderer/low_memory_mode_controller.h b/chromium/content/renderer/low_memory_mode_controller.h deleted file mode 100644 index 2038a68600c..00000000000 --- a/chromium/content/renderer/low_memory_mode_controller.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_LOW_MEMORY_MODE_CONTROLLER_H_ -#define CONTENT_RENDERER_LOW_MEMORY_MODE_CONTROLLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "content/common/content_export.h" - -namespace content { - -// The LowMemoryModeController manages for a renderer process the blink -// main thread isolate's memory savings mode state. This is only enabled -// if the V8LowMemoryModeForNonMainFrames feature and --site-per-process -// are enabled. -// -// When a process only contains subframes, the memory saving mode is -// enabled. If a main frame is later created, then the mode is disabled -// for the duration of the main frame's existence. -// -// The default state after initialization is to not enable low memory mode. -class CONTENT_EXPORT LowMemoryModeController { - public: - LowMemoryModeController(); - ~LowMemoryModeController(); - - // Notifies the controller that a frame has either been created or - // destroyed. A transition to the memory saving mode may occur as a result. - void OnFrameCreated(bool is_main_frame); - void OnFrameDestroyed(bool is_main_frame); - - bool is_enabled() const { return is_enabled_; } - - private: - // Puts the main thread isolate into memory savings mode if it is not - // currently enabled. - void Enable(); - - // Takes the main thread isolate out of memory savings mode if it is - // currently enabled. - void Disable(); - - // Records an UMA histogram marking an Enabled->Disabled state transition, - // or vice versa. - void RecordHistogram(bool enabled); - - int main_frame_count_ = 0; - bool is_enabled_ = false; - - DISALLOW_COPY_AND_ASSIGN(LowMemoryModeController); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_LOW_MEMORY_MODE_CONTROLLER_H_ diff --git a/chromium/content/renderer/low_memory_mode_controller_unittest.cc b/chromium/content/renderer/low_memory_mode_controller_unittest.cc deleted file mode 100644 index 00f0fa81f45..00000000000 --- a/chromium/content/renderer/low_memory_mode_controller_unittest.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/low_memory_mode_controller.h" - -#include "base/test/metrics/histogram_tester.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { -namespace { - -class LowMemoryModeControllerTest : public testing::Test { - public: - LowMemoryModeController* controller() { return &controller_; } - - void ExpectTransitionCount(int enabled_count, int disabled_count) { - static constexpr char kHistogram[] = - "SiteIsolation.LowMemoryMode.Transition"; - histogram_tester_.ExpectBucketCount(kHistogram, true, enabled_count); - histogram_tester_.ExpectBucketCount(kHistogram, false, disabled_count); - histogram_tester_.ExpectTotalCount(kHistogram, - enabled_count + disabled_count); - } - - private: - base::HistogramTester histogram_tester_; - LowMemoryModeController controller_; -}; - -TEST_F(LowMemoryModeControllerTest, CreateMainFrames) { - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameCreated(true); - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameCreated(true); - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameDestroyed(true); - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameDestroyed(true); - EXPECT_TRUE(controller()->is_enabled()); - - ExpectTransitionCount(1, 0); -} - -TEST_F(LowMemoryModeControllerTest, MainFrameAddSubframe) { - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameCreated(true); - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameCreated(false); - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameDestroyed(true); - EXPECT_TRUE(controller()->is_enabled()); - - controller()->OnFrameDestroyed(false); - EXPECT_TRUE(controller()->is_enabled()); - - ExpectTransitionCount(1, 0); -} - -TEST_F(LowMemoryModeControllerTest, SubFrameAddMainFrame) { - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameCreated(false); - EXPECT_TRUE(controller()->is_enabled()); - - controller()->OnFrameCreated(true); - EXPECT_FALSE(controller()->is_enabled()); - - controller()->OnFrameDestroyed(true); - EXPECT_TRUE(controller()->is_enabled()); - - controller()->OnFrameDestroyed(false); - EXPECT_TRUE(controller()->is_enabled()); - - ExpectTransitionCount(2, 1); -} - -} // namespace -} // namespace content diff --git a/chromium/content/renderer/media/android/media_player_renderer_client.cc b/chromium/content/renderer/media/android/media_player_renderer_client.cc index fc95fdf46cc..c5675501e37 100644 --- a/chromium/content/renderer/media/android/media_player_renderer_client.cc +++ b/chromium/content/renderer/media/android/media_player_renderer_client.cc @@ -67,12 +67,6 @@ void MediaPlayerRendererClient::Initialize( weak_factory_.GetWeakPtr(), media_resource)); } -void MediaPlayerRendererClient::SetCdm(media::CdmContext* cdm_context, - media::CdmAttachedCB cdm_attached_cb) { - // MediaPlayerRenderer does not support encrypted media. - NOTREACHED(); -} - void MediaPlayerRendererClient::OnStreamTextureWrapperInitialized( media::MediaResource* media_resource, bool success) { diff --git a/chromium/content/renderer/media/android/media_player_renderer_client.h b/chromium/content/renderer/media/android/media_player_renderer_client.h index 19754f24de4..9bc67210d5e 100644 --- a/chromium/content/renderer/media/android/media_player_renderer_client.h +++ b/chromium/content/renderer/media/android/media_player_renderer_client.h @@ -61,8 +61,6 @@ class CONTENT_EXPORT MediaPlayerRendererClient void Initialize(media::MediaResource* media_resource, media::RendererClient* client, media::PipelineStatusCallback init_cb) override; - void SetCdm(media::CdmContext* cdm_context, - media::CdmAttachedCB cdm_attached_cb) override; // media::mojom::MediaPlayerRendererClientExtension implementation void OnDurationChange(base::TimeDelta duration) override; diff --git a/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc b/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc index a02c70aac50..35119cfd491 100644 --- a/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc +++ b/chromium/content/renderer/media/android/stream_texture_wrapper_impl.cc @@ -7,9 +7,11 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" +#include "base/logging.h" #include "cc/layers/video_frame_provider.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/shared_image_interface.h" +#include "gpu/command_buffer/common/shared_image_usage.h" #include "media/base/bind_to_current_loop.h" namespace { @@ -62,6 +64,11 @@ void StreamTextureWrapperImpl::CreateVideoFrame( gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes] = { gpu::MailboxHolder(mailbox, gpu::SyncToken(), GL_TEXTURE_EXTERNAL_OES)}; + gpu::SharedImageInterface* sii = factory_->SharedImageInterface(); + sii->NotifyMailboxAdded(mailbox, gpu::SHARED_IMAGE_USAGE_DISPLAY | + gpu::SHARED_IMAGE_USAGE_GLES2 | + gpu::SHARED_IMAGE_USAGE_RASTER); + // The pixel format doesn't matter here as long as it's valid for texture // frames. But SkiaRenderer wants to ensure that the format of the resource // used here which will eventually create a promise image must match the @@ -78,10 +85,8 @@ void StreamTextureWrapperImpl::CreateVideoFrame( coded_size, visible_rect, visible_rect.size(), base::TimeDelta()); new_frame->set_ycbcr_info(ycbcr_info); - if (enable_texture_copy_) { - new_frame->metadata()->SetBoolean(media::VideoFrameMetadata::COPY_REQUIRED, - true); - } + if (enable_texture_copy_) + new_frame->metadata()->copy_required = true; SetCurrentFrameInternal(new_frame); } diff --git a/chromium/content/renderer/media/audio/audio_device_factory.cc b/chromium/content/renderer/media/audio/audio_device_factory.cc index 2a5d45c9e1f..39b0a2b400a 100644 --- a/chromium/content/renderer/media/audio/audio_device_factory.cc +++ b/chromium/content/renderer/media/audio/audio_device_factory.cc @@ -43,16 +43,16 @@ namespace { // In this case we will time out, to avoid renderer hang forever waiting for // device authorization (http://crbug/615589). This will result in "no audio". // There are also cases when authorization takes too long on Mac and Linux. -constexpr int64_t kMaxAuthorizationTimeoutMs = 10000; +constexpr base::TimeDelta kMaxAuthorizationTimeout = + base::TimeDelta::FromSeconds(10); #else -constexpr int64_t kMaxAuthorizationTimeoutMs = 0; // No timeout. +constexpr base::TimeDelta kMaxAuthorizationTimeout; // No timeout. #endif base::TimeDelta GetDefaultAuthTimeout() { // Set authorization request timeout at 80% of renderer hung timeout, // but no more than kMaxAuthorizationTimeout. - return base::TimeDelta::FromMilliseconds( - std::min(kHungRendererDelayMs * 8 / 10, kMaxAuthorizationTimeoutMs)); + return std::min(kHungRendererDelay * 8 / 10, kMaxAuthorizationTimeout); } scoped_refptr<media::AudioOutputDevice> NewOutputDevice( @@ -181,7 +181,8 @@ AudioDeviceFactory::NewAudioCapturerSource( return base::MakeRefCounted<media::AudioInputDevice>( AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id, params), - media::AudioInputDevice::Purpose::kUserInput); + media::AudioInputDevice::Purpose::kUserInput, + media::AudioInputDevice::DeadStreamDetection::kEnabled); } // static diff --git a/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.cc b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.cc index a5301686b4c..2518e7f289e 100644 --- a/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.cc +++ b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -98,30 +99,6 @@ media::AudioParameters GetMixerOutputParams( return params; } -void LogMixerUmaHistogram(media::AudioLatency::LatencyType latency, int value) { - switch (latency) { - case media::AudioLatency::LATENCY_EXACT_MS: - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Media.Audio.Render.AudioInputsPerMixer.LatencyExact", value, 1, 20, - 21); - return; - case media::AudioLatency::LATENCY_INTERACTIVE: - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Media.Audio.Render.AudioInputsPerMixer.LatencyInteractive", value, 1, - 20, 21); - return; - case media::AudioLatency::LATENCY_RTC: - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Media.Audio.Render.AudioInputsPerMixer.LatencyRtc", value, 1, 20, - 21); - return; - case media::AudioLatency::LATENCY_PLAYBACK: - return; - default: - NOTREACHED(); - } -} - } // namespace namespace content { @@ -193,9 +170,8 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( const media::AudioParameters& mixer_output_params = GetMixerOutputParams(input_params, sink_info.output_params(), latency); - media::AudioRendererMixer* mixer = new media::AudioRendererMixer( - mixer_output_params, std::move(sink), - base::BindRepeating(&LogMixerUmaHistogram, latency)); + media::AudioRendererMixer* mixer = + new media::AudioRendererMixer(mixer_output_params, std::move(sink)); mixers_[key] = {mixer, 1}; DVLOG(1) << __func__ << " mixer: " << mixer << " latency: " << latency << "\n input: " << input_params.AsHumanReadableString() diff --git a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc index 02e2a9a54f2..3fa811c782a 100644 --- a/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc +++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc @@ -34,10 +34,8 @@ class AudioRendererSinkCacheImpl::FrameObserver : public RenderFrameObserver { private: // content::RenderFrameObserver implementation: - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override { - if (!is_same_document_navigation) - DropFrameCache(); + void DidCommitProvisionalLoad(ui::PageTransition transition) override { + DropFrameCache(); } void OnDestruct() override { diff --git a/chromium/content/renderer/media/batching_media_log.cc b/chromium/content/renderer/media/batching_media_log.cc index a1a101687cc..76ebdf6f7a1 100644 --- a/chromium/content/renderer/media/batching_media_log.cc +++ b/chromium/content/renderer/media/batching_media_log.cc @@ -117,7 +117,8 @@ void BatchingMediaLog::AddLogRecordLocked( case media::MediaLogRecord::Type::kMessage: queued_media_events_.push_back(*event); if (event->params.HasKey(media::MediaLogMessageLevelToString( - media::MediaLogMessageLevel::kERROR))) { + media::MediaLogMessageLevel::kERROR)) && + !cached_media_error_for_message_) { cached_media_error_for_message_ = std::move(event); } break; diff --git a/chromium/content/renderer/media/batching_media_log_unittest.cc b/chromium/content/renderer/media/batching_media_log_unittest.cc index ccd285a3c04..feae6558a93 100644 --- a/chromium/content/renderer/media/batching_media_log_unittest.cc +++ b/chromium/content/renderer/media/batching_media_log_unittest.cc @@ -68,6 +68,10 @@ class BatchingMediaLogTest : public testing::Test { return return_events; } + void AddMessage(media::MediaLogMessageLevel level, std::string message) { + log_.AddMessage(level, message); + } + private: friend class TestEventHandler; void AddEventsForTesting(std::vector<media::MediaLogRecord> events) { @@ -157,4 +161,12 @@ TEST_F(BatchingMediaLogTest, DurationChanged) { EXPECT_EQ(media::MediaLogRecord::Type::kMediaEventTriggered, events[2].type); } +TEST_F(BatchingMediaLogTest, OnlyKeepsFirstErrorStringMessage) { + AddMessage(media::MediaLogMessageLevel::kERROR, "first error"); + AddMessage(media::MediaLogMessageLevel::kERROR, "second error"); + log_.NotifyError(media::DEMUXER_ERROR_DETECTED_HLS); + + ASSERT_EQ(log_.GetErrorMessage(), "DEMUXER_ERROR_DETECTED_HLS: first error"); +} + } // namespace content diff --git a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc index 77baecdaad4..a411ffbaafb 100644 --- a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc +++ b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc @@ -25,6 +25,7 @@ #include "gpu/ipc/client/command_buffer_proxy_impl.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/common/gpu_memory_buffer_support.h" +#include "media/base/bind_to_current_loop.h" #include "media/gpu/gpu_video_accelerator_util.h" #include "media/gpu/ipc/common/media_messages.h" #include "media/mojo/buildflags.h" @@ -52,6 +53,26 @@ void RecordContextProviderPhaseUmaEnum(const ContextProviderPhase phase) { } // namespace +GpuVideoAcceleratorFactoriesImpl::Notifier::Notifier() = default; +GpuVideoAcceleratorFactoriesImpl::Notifier::~Notifier() = default; + +void GpuVideoAcceleratorFactoriesImpl::Notifier::Register( + base::OnceClosure callback) { + if (is_notified_) { + std::move(callback).Run(); + return; + } + callbacks_.push_back(std::move(callback)); +} + +void GpuVideoAcceleratorFactoriesImpl::Notifier::Notify() { + DCHECK(!is_notified_); + is_notified_ = true; + for (auto& callback : callbacks_) + std::move(callback).Run(); + callbacks_.clear(); +} + // static std::unique_ptr<GpuVideoAcceleratorFactoriesImpl> GpuVideoAcceleratorFactoriesImpl::Create( @@ -124,6 +145,8 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner( if (context_provider_->BindToCurrentThread() != gpu::ContextResult::kSuccess) { + OnDecoderSupportFailed(); + OnEncoderSupportFailed(); OnContextLost(); return; } @@ -140,10 +163,15 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner( .video_encode_accelerator_supported_profiles); } + vea_provider_.set_disconnect_handler(base::BindOnce( + &GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed, + base::Unretained(this))); vea_provider_->GetVideoEncodeAcceleratorSupportedProfiles( base::BindOnce(&GpuVideoAcceleratorFactoriesImpl:: OnGetVideoEncodeAcceleratorSupportedProfiles, base::Unretained(this))); + } else { + OnEncoderSupportFailed(); } #if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) @@ -154,17 +182,56 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner( // kAlternate, for example. interface_factory_->CreateVideoDecoder( video_decoder_.BindNewPipeAndPassReceiver()); + video_decoder_.set_disconnect_handler( + base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed, + base::Unretained(this))); video_decoder_->GetSupportedConfigs(base::BindOnce( &GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs, base::Unretained(this))); +#else + OnDecoderSupportFailed(); #endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) } +bool GpuVideoAcceleratorFactoriesImpl::IsDecoderSupportKnown() { + base::AutoLock lock(supported_profiles_lock_); + return decoder_support_notifier_.is_notified(); +} + +void GpuVideoAcceleratorFactoriesImpl::NotifyDecoderSupportKnown( + base::OnceClosure callback) { + base::AutoLock lock(supported_profiles_lock_); + decoder_support_notifier_.Register( + media::BindToCurrentLoop(std::move(callback))); +} + void GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs( const media::SupportedVideoDecoderConfigMap& supported_configs) { base::AutoLock lock(supported_profiles_lock_); + video_decoder_.reset(); supported_decoder_configs_ = supported_configs; + decoder_support_notifier_.Notify(); +} + +void GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed() { + base::AutoLock lock(supported_profiles_lock_); video_decoder_.reset(); + if (decoder_support_notifier_.is_notified()) + return; + supported_decoder_configs_ = media::SupportedVideoDecoderConfigMap(); + decoder_support_notifier_.Notify(); +} + +bool GpuVideoAcceleratorFactoriesImpl::IsEncoderSupportKnown() { + base::AutoLock lock(supported_profiles_lock_); + return encoder_support_notifier_.is_notified(); +} + +void GpuVideoAcceleratorFactoriesImpl::NotifyEncoderSupportKnown( + base::OnceClosure callback) { + base::AutoLock lock(supported_profiles_lock_); + encoder_support_notifier_.Register( + media::BindToCurrentLoop(std::move(callback))); } void GpuVideoAcceleratorFactoriesImpl:: @@ -173,6 +240,15 @@ void GpuVideoAcceleratorFactoriesImpl:: supported_profiles) { base::AutoLock lock(supported_profiles_lock_); supported_vea_profiles_ = supported_profiles; + encoder_support_notifier_.Notify(); +} + +void GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed() { + base::AutoLock lock(supported_profiles_lock_); + if (encoder_support_notifier_.is_notified()) + return; + supported_vea_profiles_ = media::VideoEncodeAccelerator::SupportedProfiles(); + encoder_support_notifier_.Notify(); } bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() { diff --git a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h index c15269de003..4bc4f75cc36 100644 --- a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h +++ b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h @@ -76,13 +76,19 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl bool IsGpuVideoAcceleratorEnabled() override; base::UnguessableToken GetChannelToken() override; int32_t GetCommandBufferRouteId() override; + Supported IsDecoderConfigSupported( + media::VideoDecoderImplementation implementation, + const media::VideoDecoderConfig& config) override; + bool IsDecoderSupportKnown() override; + void NotifyDecoderSupportKnown(base::OnceClosure callback) override; std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( media::MediaLog* media_log, media::VideoDecoderImplementation implementation, media::RequestOverlayInfoCB request_overlay_info_cb) override; - Supported IsDecoderConfigSupported( - media::VideoDecoderImplementation implementation, - const media::VideoDecoderConfig& config) override; + base::Optional<media::VideoEncodeAccelerator::SupportedProfiles> + GetVideoEncodeAcceleratorSupportedProfiles() override; + bool IsEncoderSupportKnown() override; + void NotifyEncoderSupportKnown(base::OnceClosure callback) override; std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator() override; @@ -113,9 +119,6 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl base::UnsafeSharedMemoryRegion CreateSharedMemoryRegion(size_t size) override; scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override; - base::Optional<media::VideoEncodeAccelerator::SupportedProfiles> - GetVideoEncodeAcceleratorSupportedProfiles() override; - viz::RasterContextProvider* GetMediaContextProvider() override; void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override; @@ -128,6 +131,21 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl ~GpuVideoAcceleratorFactoriesImpl() override; private: + class Notifier { + public: + Notifier(); + ~Notifier(); + + void Register(base::OnceClosure callback); + void Notify(); + + bool is_notified() { return is_notified_; } + + private: + bool is_notified_ = false; + std::vector<base::OnceClosure> callbacks_; + }; + GpuVideoAcceleratorFactoriesImpl( scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, const scoped_refptr<base::SingleThreadTaskRunner>& @@ -154,9 +172,12 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl void OnSupportedDecoderConfigs( const media::SupportedVideoDecoderConfigMap& supported_configs); + void OnDecoderSupportFailed(); + void OnGetVideoEncodeAcceleratorSupportedProfiles( const media::VideoEncodeAccelerator::SupportedProfiles& supported_profiles); + void OnEncoderSupportFailed(); const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -197,9 +218,11 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl // are no supported configs. base::Optional<media::SupportedVideoDecoderConfigMap> supported_decoder_configs_ GUARDED_BY(supported_profiles_lock_); + Notifier decoder_support_notifier_ GUARDED_BY(supported_profiles_lock_); base::Optional<media::VideoEncodeAccelerator::SupportedProfiles> supported_vea_profiles_ GUARDED_BY(supported_profiles_lock_); + Notifier encoder_support_notifier_ GUARDED_BY(supported_profiles_lock_); // For sending requests to allocate shared memory in the Browser process. scoped_refptr<ThreadSafeSender> thread_safe_sender_; diff --git a/chromium/content/renderer/media/media_factory.cc b/chromium/content/renderer/media/media_factory.cc index a1c33d76de6..9ef13848286 100644 --- a/chromium/content/renderer/media/media_factory.cc +++ b/chromium/content/renderer/media/media_factory.cc @@ -18,6 +18,7 @@ #include "cc/trees/layer_tree_settings.h" #include "content/public/common/content_client.h" #include "content/public/renderer/content_renderer_client.h" +#include "content/public/renderer/render_frame_media_playback_options.h" #include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/batching_media_log.h" #include "content/renderer/media/inspector_media_event_handler.h" @@ -61,6 +62,7 @@ #include "url/origin.h" #if defined(OS_ANDROID) +#include "components/viz/common/features.h" #include "content/renderer/media/android/flinging_renderer_client_factory.h" #include "content/renderer/media/android/media_player_renderer_client_factory.h" #include "content/renderer/media/android/stream_texture_wrapper_impl.h" @@ -91,10 +93,18 @@ #endif #if BUILDFLAG(ENABLE_MEDIA_REMOTING) +// Enable remoting sender #include "media/remoting/courier_renderer_factory.h" // nogncheck #include "media/remoting/renderer_controller.h" // nogncheck #endif +#if BUILDFLAG(IS_CHROMECAST) +// Enable remoting receiver +#include "media/remoting/receiver_controller.h" // nogncheck +#include "media/remoting/remoting_constants.h" // nogncheck +#include "media/remoting/remoting_renderer_factory.h" // nogncheck +#endif + namespace { class FrameFetchContext : public media::ResourceFetchContext { public: @@ -157,6 +167,26 @@ void LogRoughness(media::MediaLog* media_log, media_log->SetProperty<media::MediaLogProperty::kFramerate>(fps); } +std::unique_ptr<media::DefaultRendererFactory> CreateDefaultRendererFactory( + media::MediaLog* media_log, + media::DecoderFactory* decoder_factory, + content::RenderThreadImpl* render_thread, + content::RenderFrameImpl* render_frame) { +#if defined(OS_ANDROID) + auto default_factory = std::make_unique<media::DefaultRendererFactory>( + media_log, decoder_factory, + base::BindRepeating(&content::RenderThreadImpl::GetGpuFactories, + base::Unretained(render_thread))); +#else + auto default_factory = std::make_unique<media::DefaultRendererFactory>( + media_log, decoder_factory, + base::BindRepeating(&content::RenderThreadImpl::GetGpuFactories, + base::Unretained(render_thread)), + render_frame->CreateSpeechRecognitionClient(base::OnceClosure())); +#endif + return default_factory; +} + } // namespace namespace content { @@ -165,7 +195,8 @@ namespace content { blink::WebMediaPlayer::SurfaceLayerMode MediaFactory::GetVideoSurfaceLayerMode() { #if defined(OS_ANDROID) - if (base::FeatureList::IsEnabled(media::kDisableSurfaceLayerForVideo)) + if (base::FeatureList::IsEnabled(media::kDisableSurfaceLayerForVideo) && + !features::IsUsingVizForWebView()) return blink::WebMediaPlayer::SurfaceLayerMode::kNever; #endif // OS_ANDROID @@ -327,9 +358,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer( const WebPreferences webkit_preferences = render_frame_->GetWebkitPreferences(); bool embedded_media_experience_enabled = false; - bool use_media_player_renderer = false; #if defined(OS_ANDROID) - use_media_player_renderer = UseMediaPlayerRenderer(url); embedded_media_experience_enabled = webkit_preferences.embedded_media_experience_enabled; #endif // defined(OS_ANDROID) @@ -360,9 +389,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer( base::WeakPtr<media::MediaObserver> media_observer; auto factory_selector = CreateRendererFactorySelector( - media_log.get(), use_media_player_renderer, - render_frame_->GetRenderFrameMediaPlaybackOptions() - .is_mojo_renderer_enabled(), + media_log.get(), url, render_frame_->GetRenderFrameMediaPlaybackOptions(), GetDecoderFactory(), std::make_unique<media::RemotePlaybackClientWrapperImpl>(client), &media_observer); @@ -446,8 +473,6 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer( .is_background_video_playback_enabled, render_frame_->GetRenderFrameMediaPlaybackOptions() .is_background_video_track_optimization_supported, - render_frame_->GetRenderFrameMediaPlaybackOptions() - .is_remoting_renderer_enabled(), GetContentClient()->renderer()->OverrideDemuxerForUrl( render_frame_, url, media_task_runner), std::move(power_status_helper))); @@ -475,8 +500,8 @@ blink::WebEncryptedMediaClient* MediaFactory::EncryptedMediaClient() { std::unique_ptr<media::RendererFactorySelector> MediaFactory::CreateRendererFactorySelector( media::MediaLog* media_log, - bool use_media_player, - bool enable_mojo_renderer, + blink::WebURL url, + const RenderFrameMediaPlaybackOptions& renderer_media_playback_options, media::DecoderFactory* decoder_factory, std::unique_ptr<media::RemotePlaybackClientWrapper> client_wrapper, base::WeakPtr<media::MediaObserver>* out_media_observer) { @@ -489,6 +514,11 @@ MediaFactory::CreateRendererFactorySelector( auto factory_selector = std::make_unique<media::RendererFactorySelector>(); bool use_default_renderer_factory = true; + bool use_media_player_renderer = false; + +#if defined(OS_ANDROID) + use_media_player_renderer = UseMediaPlayerRenderer(url); +#endif // defined(OS_ANDROID) #if defined(OS_ANDROID) DCHECK(interface_broker_); @@ -503,7 +533,7 @@ MediaFactory::CreateRendererFactorySelector( render_thread->GetStreamTexureFactory(), render_frame_->GetTaskRunner(blink::TaskType::kInternalMedia))); - if (use_media_player) { + if (use_media_player_renderer) { factory_selector->AddBaseFactory(FactoryType::kMediaPlayer, std::move(media_player_factory)); use_default_renderer_factory = false; @@ -534,8 +564,8 @@ MediaFactory::CreateRendererFactorySelector( #endif // defined(OS_ANDROID) #if BUILDFLAG(ENABLE_MOJO_RENDERER) - DCHECK(!use_media_player); - if (enable_mojo_renderer) { + DCHECK(!use_media_player_renderer); + if (renderer_media_playback_options.is_mojo_renderer_enabled()) { use_default_renderer_factory = false; #if BUILDFLAG(ENABLE_CAST_RENDERER) factory_selector->AddBaseFactory( @@ -565,18 +595,9 @@ MediaFactory::CreateRendererFactorySelector( #endif // defined(OS_FUCHSIA) if (use_default_renderer_factory) { -#if defined(OS_ANDROID) - auto default_factory = std::make_unique<media::DefaultRendererFactory>( - media_log, decoder_factory, - base::BindRepeating(&RenderThreadImpl::GetGpuFactories, - base::Unretained(render_thread))); -#else - auto default_factory = std::make_unique<media::DefaultRendererFactory>( - media_log, decoder_factory, - base::BindRepeating(&RenderThreadImpl::GetGpuFactories, - base::Unretained(render_thread)), - render_frame_->CreateSpeechRecognitionClient()); -#endif + DCHECK(!use_media_player_renderer); + auto default_factory = CreateDefaultRendererFactory( + media_log, decoder_factory, render_thread, render_frame_); factory_selector->AddBaseFactory(FactoryType::kDefault, std::move(default_factory)); } @@ -606,6 +627,27 @@ MediaFactory::CreateRendererFactorySelector( FactoryType::kCourier, std::move(courier_factory), is_remoting_cb); #endif +#if BUILDFLAG(IS_CHROMECAST) + if (renderer_media_playback_options.is_remoting_renderer_enabled()) { + auto default_factory = CreateDefaultRendererFactory( + media_log, decoder_factory, render_thread, render_frame_); + mojo::PendingRemote<media::mojom::Remotee> remotee; + interface_broker_->GetInterface(remotee.InitWithNewPipeAndPassReceiver()); + auto remoting_renderer_factory = + std::make_unique<media::remoting::RemotingRendererFactory>( + std::move(remotee), std::move(default_factory), + render_thread->GetMediaThreadTaskRunner()); + auto is_remoting_media = base::BindRepeating( + [](const GURL& url) -> bool { + return url.SchemeIs(media::remoting::kRemotingScheme); + }, + url); + factory_selector->AddConditionalFactory( + FactoryType::kRemoting, std::move(remoting_renderer_factory), + is_remoting_media); + } +#endif // BUILDFLAG(IS_CHROMECAST) + return factory_selector; } diff --git a/chromium/content/renderer/media/media_factory.h b/chromium/content/renderer/media/media_factory.h index 508690707a4..731e7619ced 100644 --- a/chromium/content/renderer/media/media_factory.h +++ b/chromium/content/renderer/media/media_factory.h @@ -9,6 +9,7 @@ #include "base/memory/weak_ptr.h" #include "build/buildflag.h" +#include "build/chromecast_buildflags.h" #include "components/viz/common/surfaces/surface_id.h" #include "media/base/renderer_factory_selector.h" #include "media/base/routing_token_callback.h" @@ -18,7 +19,6 @@ #include "media/mojo/buildflags.h" #include "media/mojo/clients/mojo_renderer_factory.h" #include "media/mojo/mojom/interface_factory.mojom.h" -#include "media/mojo/mojom/remoting.mojom.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/platform/web_media_player_source.h" #include "third_party/blink/public/platform/web_security_origin.h" @@ -26,6 +26,11 @@ #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/web/web_media_inspector.h" +#if BUILDFLAG(ENABLE_MEDIA_REMOTING) +// Needed by remoting sender. +#include "media/mojo/mojom/remoting.mojom.h" +#endif // BUILDFLAG(ENABLE_MEDIA_REMOTING) + namespace blink { class BrowserInterfaceBrokerProxy; class WebContentDecryptionModule; @@ -55,6 +60,7 @@ namespace content { class RenderFrameImpl; class MediaInterfaceFactory; +struct RenderFrameMediaPlaybackOptions; // Assist to RenderFrameImpl in creating various media clients. class MediaFactory { @@ -113,8 +119,8 @@ class MediaFactory { private: std::unique_ptr<media::RendererFactorySelector> CreateRendererFactorySelector( media::MediaLog* media_log, - bool use_media_player, - bool enable_mojo_renderer, + blink::WebURL url, + const RenderFrameMediaPlaybackOptions& renderer_media_playback_options, media::DecoderFactory* decoder_factory, std::unique_ptr<media::RemotePlaybackClientWrapper> client_wrapper, base::WeakPtr<media::MediaObserver>* out_media_observer); diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc index ae04d071938..00b74f52fe3 100644 --- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc +++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc @@ -207,6 +207,11 @@ void RendererWebMediaPlayerDelegate::DidPictureInPictureAvailabilityChange( routing_id(), delegate_id, available)); } +void RendererWebMediaPlayerDelegate::DidBufferUnderflow(int player_id) { + Send(new MediaPlayerDelegateHostMsg_OnBufferUnderflow(routing_id(), + player_id)); +} + void RendererWebMediaPlayerDelegate::WasHidden() { RecordAction(base::UserMetricsAction("Media.Hidden")); diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h index 2b4181601d6..a2ae5b93c63 100644 --- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h +++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h @@ -70,6 +70,7 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate const media_session::MediaPosition& position) override; void DidPictureInPictureAvailabilityChange(int delegate_id, bool available) override; + void DidBufferUnderflow(int player_id) override; // content::RenderFrameObserver overrides. void WasHidden() override; diff --git a/chromium/content/renderer/mouse_lock_dispatcher.h b/chromium/content/renderer/mouse_lock_dispatcher.h index 7e2838de8a5..d0388d0e776 100644 --- a/chromium/content/renderer/mouse_lock_dispatcher.h +++ b/chromium/content/renderer/mouse_lock_dispatcher.h @@ -7,8 +7,8 @@ #include "base/macros.h" #include "content/common/content_export.h" -#include "content/common/input/input_handler.mojom.h" #include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/input/pointer_lock_context.mojom.h" #include "third_party/blink/public/web/web_widget_client.h" namespace blink { diff --git a/chromium/content/renderer/navigation_client.cc b/chromium/content/renderer/navigation_client.cc index c86b9f7f6be..0d9b602a12f 100644 --- a/chromium/content/renderer/navigation_client.cc +++ b/chromium/content/renderer/navigation_client.cc @@ -25,7 +25,7 @@ void NavigationClient::CommitNavigation( base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory, const base::UnguessableToken& devtools_navigation_token, @@ -35,12 +35,12 @@ void NavigationClient::CommitNavigation( // race conditions leading to the early deletion of NavigationRequest would // unexpectedly abort the ongoing navigation. Remove when the races are fixed. ResetDisconnectionHandler(); - render_frame_->CommitPerNavigationMojoInterfaceNavigation( + render_frame_->CommitNavigation( std::move(common_params), std::move(commit_params), std::move(response_head), std::move(response_body), std::move(url_loader_client_endpoints), std::move(subresource_loaders), std::move(subresource_overrides), - std::move(controller_service_worker_info), std::move(provider_info), + std::move(controller_service_worker_info), std::move(container_info), std::move(prefetch_loader_factory), devtools_navigation_token, std::move(callback)); } diff --git a/chromium/content/renderer/navigation_client.h b/chromium/content/renderer/navigation_client.h index 749c04b261e..404d863bc87 100644 --- a/chromium/content/renderer/navigation_client.h +++ b/chromium/content/renderer/navigation_client.h @@ -30,7 +30,7 @@ class NavigationClient : mojom::NavigationClient { subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory, const base::UnguessableToken& devtools_navigation_token, diff --git a/chromium/content/renderer/navigation_state.cc b/chromium/content/renderer/navigation_state.cc index 9a2c4d88c00..d16d0fd6be1 100644 --- a/chromium/content/renderer/navigation_state.cc +++ b/chromium/content/renderer/navigation_state.cc @@ -16,7 +16,6 @@ namespace content { NavigationState::~NavigationState() { - RunCommitNavigationCallback(blink::mojom::CommitResult::Aborted); navigation_client_.reset(); } @@ -24,22 +23,19 @@ NavigationState::~NavigationState() { std::unique_ptr<NavigationState> NavigationState::CreateBrowserInitiated( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, - mojom::FrameNavigationControl::CommitNavigationCallback callback, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_callback, + mojom::NavigationClient::CommitNavigationCallback commit_callback, std::unique_ptr<NavigationClient> navigation_client, bool was_initiated_in_this_frame) { return base::WrapUnique(new NavigationState( std::move(common_params), std::move(commit_params), false, - std::move(callback), std::move(per_navigation_mojo_interface_callback), - std::move(navigation_client), was_initiated_in_this_frame)); + std::move(commit_callback), std::move(navigation_client), + was_initiated_in_this_frame)); } // static std::unique_ptr<NavigationState> NavigationState::CreateContentInitiated() { return base::WrapUnique(new NavigationState( CreateCommonNavigationParams(), CreateCommitNavigationParams(), true, - content::mojom::FrameNavigationControl::CommitNavigationCallback(), content::mojom::NavigationClient::CommitNavigationCallback(), nullptr, true)); } @@ -60,17 +56,12 @@ bool NavigationState::IsContentInitiated() { } void NavigationState::RunCommitNavigationCallback( - blink::mojom::CommitResult result) { - if (commit_callback_) - std::move(commit_callback_).Run(result); -} - -void NavigationState::RunPerNavigationInterfaceCommitNavigationCallback( std::unique_ptr<::FrameHostMsg_DidCommitProvisionalLoad_Params> params, mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) { - if (per_navigation_mojo_interface_commit_callback_) - std::move(per_navigation_mojo_interface_commit_callback_) + if (commit_callback_) { + std::move(commit_callback_) .Run(std::move(params), std::move(interface_params)); + } navigation_client_.reset(); } @@ -78,9 +69,7 @@ NavigationState::NavigationState( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, bool is_content_initiated, - mojom::FrameNavigationControl::CommitNavigationCallback callback, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_commit_callback, + mojom::NavigationClient::CommitNavigationCallback commit_callback, std::unique_ptr<NavigationClient> navigation_client, bool was_initiated_in_this_frame) : was_within_same_document_(false), @@ -89,7 +78,5 @@ NavigationState::NavigationState( common_params_(std::move(common_params)), commit_params_(std::move(commit_params)), navigation_client_(std::move(navigation_client)), - commit_callback_(std::move(callback)), - per_navigation_mojo_interface_commit_callback_( - std::move(per_navigation_mojo_interface_commit_callback)) {} + commit_callback_(std::move(commit_callback)) {} } // namespace content diff --git a/chromium/content/renderer/navigation_state.h b/chromium/content/renderer/navigation_state.h index 375495ca33d..bcbc454b959 100644 --- a/chromium/content/renderer/navigation_state.h +++ b/chromium/content/renderer/navigation_state.h @@ -33,7 +33,6 @@ class CONTENT_EXPORT NavigationState { static std::unique_ptr<NavigationState> CreateBrowserInitiated( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, - mojom::FrameNavigationControl::CommitNavigationCallback callback, mojom::NavigationClient::CommitNavigationCallback per_navigation_mojo_interface_callback, std::unique_ptr<NavigationClient> navigation_client, @@ -56,9 +55,7 @@ class CONTENT_EXPORT NavigationState { const mojom::CommitNavigationParams& commit_params() const { return *commit_params_; } - bool uses_per_navigation_mojo_interface() const { - return navigation_client_.get(); - } + bool has_navigation_client() const { return navigation_client_.get(); } void set_was_within_same_document(bool value) { was_within_same_document_ = value; } @@ -71,28 +68,18 @@ class CONTENT_EXPORT NavigationState { common_params_->transition = transition; } - // Only used when PerNavigationMojoInterface is enabled. - void set_navigation_client( - std::unique_ptr<NavigationClient> navigation_client_impl) { - navigation_client_ = std::move(navigation_client_impl); - } - - void RunCommitNavigationCallback(blink::mojom::CommitResult result); - - void RunPerNavigationInterfaceCommitNavigationCallback( + void RunCommitNavigationCallback( std::unique_ptr<::FrameHostMsg_DidCommitProvisionalLoad_Params> params, mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params); private: - NavigationState( - mojom::CommonNavigationParamsPtr common_params, - mojom::CommitNavigationParamsPtr commit_params, - bool is_content_initiated, - content::mojom::FrameNavigationControl::CommitNavigationCallback callback, - content::mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_callback, - std::unique_ptr<NavigationClient> navigation_client, - bool was_initiated_in_this_frame); + NavigationState(mojom::CommonNavigationParamsPtr common_params, + mojom::CommitNavigationParamsPtr commit_params, + bool is_content_initiated, + content::mojom::NavigationClient::CommitNavigationCallback + commit_callback, + std::unique_ptr<NavigationClient> navigation_client, + bool was_initiated_in_this_frame); bool was_within_same_document_; @@ -129,13 +116,7 @@ class CONTENT_EXPORT NavigationState { // Used to notify whether a commit request from the browser process was // successful or not. - mojom::FrameNavigationControl::CommitNavigationCallback commit_callback_; - - // Temporary member meant to be used in place of |commit_callback_| when - // PerNavigationMojoInterface is enabled. Should eventually replace it - // completely. - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_commit_callback_; + mojom::NavigationClient::CommitNavigationCallback commit_callback_; DISALLOW_COPY_AND_ASSIGN(NavigationState); }; diff --git a/chromium/content/renderer/pepper/event_conversion_unittest.cc b/chromium/content/renderer/pepper/event_conversion_unittest.cc index f1cb3204a76..ec2a622a6c6 100644 --- a/chromium/content/renderer/pepper/event_conversion_unittest.cc +++ b/chromium/content/renderer/pepper/event_conversion_unittest.cc @@ -8,9 +8,9 @@ #include <memory> -#include "content/common/input/synthetic_web_input_event_builders.h" #include "ppapi/shared_impl/ppb_input_event_shared.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" namespace content { @@ -43,7 +43,7 @@ class EventConversionTest : public ::testing::Test { }; TEST_F(EventConversionTest, TouchStart) { - SyntheticWebTouchEvent touch; + blink::SyntheticWebTouchEvent touch; touch.PressPoint(1.f, 2.f); std::vector<ppapi::InputEventData> pp_events; @@ -67,7 +67,7 @@ TEST_F(EventConversionTest, TouchStart) { } TEST_F(EventConversionTest, TouchMove) { - SyntheticWebTouchEvent touch; + blink::SyntheticWebTouchEvent touch; touch.PressPoint(1.f, 2.f); touch.ResetPoints(); touch.PressPoint(3.f, 4.f); @@ -95,7 +95,7 @@ TEST_F(EventConversionTest, TouchMove) { } TEST_F(EventConversionTest, TouchEnd) { - SyntheticWebTouchEvent touch; + blink::SyntheticWebTouchEvent touch; touch.PressPoint(1.f, 2.f); touch.ResetPoints(); touch.PressPoint(3.f, 4.f); @@ -123,7 +123,7 @@ TEST_F(EventConversionTest, TouchEnd) { } TEST_F(EventConversionTest, TouchCancel) { - SyntheticWebTouchEvent touch; + blink::SyntheticWebTouchEvent touch; touch.PressPoint(1.f, 2.f); touch.ResetPoints(); touch.PressPoint(3.f, 4.f); @@ -153,8 +153,9 @@ TEST_F(EventConversionTest, TouchCancel) { TEST_F(EventConversionTest, MouseMove) { std::unique_ptr<gfx::PointF> last_mouse_position; - blink::WebMouseEvent mouse_event = SyntheticWebMouseEventBuilder::Build( - blink::WebInputEvent::Type::kMouseMove, 100, 200, 0); + blink::WebMouseEvent mouse_event = + blink::SyntheticWebMouseEventBuilder::Build( + blink::WebInputEvent::Type::kMouseMove, 100, 200, 0); std::vector<ppapi::InputEventData> pp_events; CreateInputEventData(mouse_event, &last_mouse_position, &pp_events); @@ -170,7 +171,7 @@ TEST_F(EventConversionTest, MouseMove) { gfx::PointF(mouse_event.PositionInScreen())); } - mouse_event = SyntheticWebMouseEventBuilder::Build( + mouse_event = blink::SyntheticWebMouseEventBuilder::Build( blink::WebInputEvent::Type::kMouseMove, 123, 188, 0); CreateInputEventData(mouse_event, &last_mouse_position, &pp_events); ASSERT_EQ(PP_INPUTEVENT_TYPE_MOUSEMOVE, pp_event.event_type); diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc index baa8f2c7e0a..4ec293cbfab 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc +++ b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc @@ -24,9 +24,10 @@ namespace { #if defined(OS_WIN) || defined(OS_MACOSX) -const int64_t kMaxAuthorizationTimeoutMs = 4000; +constexpr base::TimeDelta kMaxAuthorizationTimeout = + base::TimeDelta::FromSeconds(4); #else -const int64_t kMaxAuthorizationTimeoutMs = 0; // No timeout. +constexpr base::TimeDelta kMaxAuthorizationTimeout; // No timeout. #endif } @@ -44,8 +45,7 @@ PepperPlatformAudioOutputDev* PepperPlatformAudioOutputDev::Create( render_frame_id, device_id, // Set authorization request timeout at 80% of renderer hung timeout, // but no more than kMaxAuthorizationTimeout. - base::TimeDelta::FromMilliseconds(std::min( - kHungRendererDelayMs * 8 / 10, kMaxAuthorizationTimeoutMs)))); + std::min(kHungRendererDelay * 8 / 10, kMaxAuthorizationTimeout))); if (audio_output->Initialize(sample_rate, frames_per_buffer, client)) { // Balanced by Release invoked in diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc index e0a663c1e38..18b21cb9dda 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc @@ -110,17 +110,14 @@ #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_document_loader.h" #include "third_party/blink/public/web/web_frame_widget.h" -#include "third_party/blink/public/web/web_ime_text_span.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_plugin_container.h" #include "third_party/blink/public/web/web_plugin_script_forbidden_scope.h" #include "third_party/blink/public/web/web_print_params.h" #include "third_party/blink/public/web/web_print_preset_options.h" -#include "third_party/blink/public/web/web_print_scaling_option.h" #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_view.h" #include "third_party/khronos/GLES2/gl2.h" -#include "ui/base/cursor/cursor_lookup.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/blink/web_input_event.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -175,7 +172,6 @@ using blink::WebLocalFrame; using blink::WebPlugin; using blink::WebPluginContainer; using blink::WebPrintParams; -using blink::WebPrintScalingOption; using blink::WebString; using blink::WebURLError; using blink::WebAssociatedURLLoaderClient; @@ -286,13 +282,13 @@ STATIC_ASSERT_MATCHING_ENUM(kMiddlePanningHorizontal, #undef STATIC_ASSERT_MATCHING_ENUM -STATIC_ASSERT_ENUM(blink::kWebPrintScalingOptionNone, +STATIC_ASSERT_ENUM(printing::mojom::PrintScalingOption::kNone, PP_PRINTSCALINGOPTION_NONE); -STATIC_ASSERT_ENUM(blink::kWebPrintScalingOptionFitToPrintableArea, +STATIC_ASSERT_ENUM(printing::mojom::PrintScalingOption::kFitToPrintableArea, PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA); -STATIC_ASSERT_ENUM(blink::kWebPrintScalingOptionSourceSize, +STATIC_ASSERT_ENUM(printing::mojom::PrintScalingOption::kSourceSize, PP_PRINTSCALINGOPTION_SOURCE_SIZE); -STATIC_ASSERT_ENUM(blink::kWebPrintScalingOptionFitToPaper, +STATIC_ASSERT_ENUM(printing::mojom::PrintScalingOption::kFitToPaper, PP_PRINTSCALINGOPTION_FIT_TO_PAPER); #undef STATIC_ASSERT_ENUM @@ -561,7 +557,8 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl( !render_frame_->GetLocalRootRenderWidget()->is_hidden(); // Set the initial focus. - SetContentAreaFocus(render_frame_->GetLocalRootRenderWidget()->has_focus()); + SetContentAreaFocus( + render_frame_->GetLocalRootRenderWidget()->GetWebWidget()->HasFocus()); if (!module_->IsProxied()) { created_in_process_instance_ = true; @@ -935,7 +932,7 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad( bool PepperPluginInstanceImpl::SendCompositionEventToPlugin( PP_InputEvent_Type type, const base::string16& text) { - std::vector<blink::WebImeTextSpan> empty; + std::vector<ui::ImeTextSpan> empty; return SendCompositionEventWithImeTextSpanInformationToPlugin( type, text, empty, static_cast<int>(text.size()), static_cast<int>(text.size())); @@ -945,7 +942,7 @@ bool PepperPluginInstanceImpl:: SendCompositionEventWithImeTextSpanInformationToPlugin( PP_InputEvent_Type type, const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { // Keep a reference on the stack. See NOTE above. @@ -994,8 +991,7 @@ bool PepperPluginInstanceImpl:: // Set the composition target. for (size_t i = 0; i < ime_text_spans.size(); ++i) { - if (ime_text_spans[i].thickness == - ui::mojom::ImeTextSpanThickness::kThick) { + if (ime_text_spans[i].thickness == ui::ImeTextSpan::Thickness::kThick) { auto it = std::find(event.composition_segment_offsets.begin(), event.composition_segment_offsets.end(), utf8_offsets[2 * i + 2]); @@ -1036,7 +1032,7 @@ bool PepperPluginInstanceImpl::HandleCompositionStart( bool PepperPluginInstanceImpl::HandleCompositionUpdate( const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { return SendCompositionEventWithImeTextSpanInformationToPlugin( @@ -2321,7 +2317,7 @@ bool PepperPluginInstanceImpl::SimulateIMEEvent( return false; render_frame_->SimulateImeCommitText( base::UTF8ToUTF16(input_event.character_text), - std::vector<blink::WebImeTextSpan>(), gfx::Range()); + std::vector<ui::ImeTextSpan>(), gfx::Range()); break; default: return false; @@ -2344,13 +2340,13 @@ void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent( base::string16 utf16_text = base::UTF8ToUTF16AndAdjustOffsets(input_event.character_text, &offsets); - std::vector<blink::WebImeTextSpan> ime_text_spans; + std::vector<ui::ImeTextSpan> ime_text_spans; for (size_t i = 2; i + 1 < offsets.size(); ++i) { - blink::WebImeTextSpan ime_text_span; + ui::ImeTextSpan ime_text_span; ime_text_span.start_offset = offsets[i]; ime_text_span.end_offset = offsets[i + 1]; if (input_event.composition_target_segment == static_cast<int32_t>(i - 2)) - ime_text_span.thickness = ui::mojom::ImeTextSpanThickness::kThick; + ime_text_span.thickness = ui::ImeTextSpan::Thickness::kThick; ime_text_spans.push_back(ime_text_span); } @@ -2723,7 +2719,7 @@ PP_Bool PepperPluginInstanceImpl::SetCursor(PP_Instance instance, SkBitmap bitmap(image_data->GetMappedBitmap()); // Make a deep copy, so that the cursor remains valid even after the original // image data gets freed. - SkBitmap dst = GetCursorBitmap(*custom_cursor); + SkBitmap dst = custom_cursor->custom_bitmap(); if (!dst.tryAllocPixels(bitmap.info()) || !bitmap.readPixels(dst.info(), dst.getPixels(), dst.rowBytes(), 0, 0)) { return PP_FALSE; diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h index 4409f64a62d..89e2352432e 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h @@ -77,7 +77,6 @@ class WebInputEvent; class WebMouseEvent; class WebPluginContainer; class WebURLResponse; -struct WebImeTextSpan; struct WebURLError; struct WebPrintParams; } // namespace blink @@ -234,7 +233,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool HandleCompositionStart(const base::string16& text); bool HandleCompositionUpdate( const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end); bool HandleCompositionEnd(const base::string16& text); @@ -630,7 +629,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool SendCompositionEventWithImeTextSpanInformationToPlugin( PP_InputEvent_Type type, const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end); diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.cc b/chromium/content/renderer/pepper/pepper_video_capture_host.cc index 6794414d61c..c1f73fee6dd 100644 --- a/chromium/content/renderer/pepper/pepper_video_capture_host.cc +++ b/chromium/content/renderer/pepper/pepper_video_capture_host.cc @@ -125,13 +125,13 @@ void PepperVideoCaptureHost::PostErrorReply() { void PepperVideoCaptureHost::OnFrameReady(const media::VideoFrame& frame) { if (alloc_size_ != frame.visible_rect().size() || buffers_.empty()) { alloc_size_ = frame.visible_rect().size(); - double frame_rate; int rounded_frame_rate; - if (frame.metadata()->GetDouble(media::VideoFrameMetadata::FRAME_RATE, - &frame_rate)) - rounded_frame_rate = static_cast<int>(frame_rate + 0.5 /* round */); - else + if (frame.metadata()->frame_rate.has_value()) { + rounded_frame_rate = + static_cast<int>(*frame.metadata()->frame_rate + 0.5 /* round */); + } else { rounded_frame_rate = blink::MediaStreamVideoSource::kUnknownFrameRate; + } AllocBuffers(alloc_size_, rounded_frame_rate); } diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc index 57d85b9f56a..330693503c9 100644 --- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc +++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc @@ -40,7 +40,6 @@ #include "third_party/blink/public/web/web_plugin_params.h" #include "third_party/blink/public/web/web_print_params.h" #include "third_party/blink/public/web/web_print_preset_options.h" -#include "third_party/blink/public/web/web_print_scaling_option.h" #include "ui/base/cursor/cursor.h" #include "ui/events/keycodes/keyboard_codes.h" #include "url/gurl.h" diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc index 4b088e4634f..9d8ffef0769 100644 --- a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc +++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc @@ -42,11 +42,10 @@ PluginPowerSaverHelper::~PluginPowerSaverHelper() { } void PluginPowerSaverHelper::DidCommitProvisionalLoad( - bool is_same_document_navigation, ui::PageTransition transition) { blink::WebFrame* frame = render_frame()->GetWebFrame(); - // Only apply to top-level and new page navigation. - if (frame->Parent() || is_same_document_navigation) + // Only apply to top-level navigation. + if (frame->Parent()) return; // Not a top-level navigation. origin_allowlist_.clear(); diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.h b/chromium/content/renderer/pepper/plugin_power_saver_helper.h index ff8497e7c15..f3c3b49bb9c 100644 --- a/chromium/content/renderer/pepper/plugin_power_saver_helper.h +++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.h @@ -52,8 +52,7 @@ class CONTENT_EXPORT PluginPowerSaverHelper : public RenderFrameObserver { void AllowlistContentOrigin(const url::Origin& content_origin); // RenderFrameObserver implementation. - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override; + void DidCommitProvisionalLoad(ui::PageTransition transition) override; bool OnMessageReceived(const IPC::Message& message) override; void OnDestruct() override; diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc index e0add969e80..16c37ec791f 100644 --- a/chromium/content/renderer/pepper/video_decoder_shim.cc +++ b/chromium/content/renderer/pepper/video_decoder_shim.cc @@ -24,7 +24,7 @@ #include "content/public/renderer/render_thread.h" #include "content/renderer/pepper/pepper_video_decoder_host.h" #include "content/renderer/render_thread_impl.h" -#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/client/raster_interface.h" #include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/limits.h" @@ -34,6 +34,7 @@ #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/vpx_video_decoder.h" #include "media/media_buildflags.h" +#include "media/renderers/yuv_util.h" #include "media/video/picture.h" #include "media/video/video_decode_accelerator.h" #include "ppapi/c/pp_errors.h" @@ -59,542 +60,6 @@ bool IsCodecSupported(media::VideoCodec codec) { } // namespace -// YUV->RGB converter class using a shader and FBO. -class VideoDecoderShim::YUVConverter { - public: - YUVConverter(scoped_refptr<viz::ContextProviderCommandBuffer>); - ~YUVConverter(); - bool Initialize(); - void Convert(const media::VideoFrame* frame, GLuint tex_out); - - private: - GLuint CreateShader(); - GLuint CompileShader(const char* name, GLuint type, const char* code); - GLuint CreateProgram(const char* name, GLuint vshader, GLuint fshader); - GLuint CreateTexture(); - - scoped_refptr<viz::ContextProviderCommandBuffer> context_provider_; - gpu::gles2::GLES2Interface* gl_; - GLuint frame_buffer_; - GLuint vertex_buffer_; - GLuint program_; - - GLuint y_texture_; - GLuint u_texture_; - GLuint v_texture_; - GLuint a_texture_; - - GLuint internal_format_; - GLuint format_; - media::VideoPixelFormat video_format_; - - GLuint y_width_; - GLuint y_height_; - - GLuint uv_width_; - GLuint uv_height_; - uint32_t uv_height_divisor_; - uint32_t uv_width_divisor_; - - GLint yuv_matrix_loc_; - GLint yuv_adjust_loc_; - - DISALLOW_COPY_AND_ASSIGN(YUVConverter); -}; - -VideoDecoderShim::YUVConverter::YUVConverter( - scoped_refptr<viz::ContextProviderCommandBuffer> context_provider) - : context_provider_(std::move(context_provider)), - gl_(context_provider_->ContextGL()), - frame_buffer_(0), - vertex_buffer_(0), - program_(0), - y_texture_(0), - u_texture_(0), - v_texture_(0), - a_texture_(0), - internal_format_(0), - format_(0), - video_format_(media::PIXEL_FORMAT_UNKNOWN), - y_width_(2), - y_height_(2), - uv_width_(2), - uv_height_(2), - uv_height_divisor_(1), - uv_width_divisor_(1), - yuv_matrix_loc_(0), - yuv_adjust_loc_(0) { - DCHECK(gl_); -} - -VideoDecoderShim::YUVConverter::~YUVConverter() { - if (y_texture_) - gl_->DeleteTextures(1, &y_texture_); - - if (u_texture_) - gl_->DeleteTextures(1, &u_texture_); - - if (v_texture_) - gl_->DeleteTextures(1, &v_texture_); - - if (a_texture_) - gl_->DeleteTextures(1, &a_texture_); - - if (frame_buffer_) - gl_->DeleteFramebuffers(1, &frame_buffer_); - - if (vertex_buffer_) - gl_->DeleteBuffers(1, &vertex_buffer_); - - if (program_) - gl_->DeleteProgram(program_); -} - -GLuint VideoDecoderShim::YUVConverter::CreateTexture() { - GLuint tex = 0; - - gl_->GenTextures(1, &tex); - gl_->BindTexture(GL_TEXTURE_2D, tex); - - // Create texture with default size - will be resized upon first frame. - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, 2, 2, 0, format_, - GL_UNSIGNED_BYTE, nullptr); - - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - gl_->BindTexture(GL_TEXTURE_2D, 0); - - return tex; -} - -GLuint VideoDecoderShim::YUVConverter::CompileShader(const char* name, - GLuint type, - const char* code) { - GLuint shader = gl_->CreateShader(type); - - gl_->ShaderSource(shader, 1, (const GLchar**)&code, nullptr); - gl_->CompileShader(shader); - -#ifndef NDEBUG - GLint status = 0; - - gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { - GLint max_length = 0; - GLint actual_length = 0; - gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length); - - // The max_length includes the NULL character. - std::string error_log(max_length, 0); - gl_->GetShaderInfoLog(shader, max_length, &actual_length, &error_log[0]); - - LOG(ERROR) << name << " shader compilation failed: " << error_log.c_str(); - gl_->DeleteShader(shader); - return 0; - } -#endif - - return shader; -} - -GLuint VideoDecoderShim::YUVConverter::CreateProgram(const char* name, - GLuint vshader, - GLuint fshader) { - GLuint program = gl_->CreateProgram(); - gl_->AttachShader(program, vshader); - gl_->AttachShader(program, fshader); - - gl_->BindAttribLocation(program, 0, "position"); - - gl_->LinkProgram(program); - -#ifndef NDEBUG - GLint status = 0; - - gl_->GetProgramiv(program, GL_LINK_STATUS, &status); - if (status != GL_TRUE) { - GLint max_length = 0; - GLint actual_length = 0; - gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); - - // The max_length includes the NULL character. - std::string error_log(max_length, 0); - gl_->GetProgramInfoLog(program, max_length, &actual_length, &error_log[0]); - - LOG(ERROR) << name << " program linking failed: " << error_log.c_str(); - return 0; - } -#endif - - return program; -} - -GLuint VideoDecoderShim::YUVConverter::CreateShader() { - const char* vert_shader = - "precision mediump float;\n" - "attribute vec2 position;\n" - "varying vec2 texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = vec4( position.xy, 0, 1 );\n" - " texcoord = position*0.5+0.5;\n" - "}"; - - const char* frag_shader = - "precision mediump float;\n" - "varying vec2 texcoord;\n" - "uniform sampler2D y_sampler;\n" - "uniform sampler2D u_sampler;\n" - "uniform sampler2D v_sampler;\n" - "uniform sampler2D a_sampler;\n" - "uniform mat3 yuv_matrix;\n" - "uniform vec3 yuv_adjust;\n" - "void main()\n" - "{\n" - " vec3 yuv = vec3(texture2D(y_sampler, texcoord).x,\n" - " texture2D(u_sampler, texcoord).x,\n" - " texture2D(v_sampler, texcoord).x) +\n" - " yuv_adjust;\n" - " gl_FragColor = vec4(yuv_matrix * yuv, texture2D(a_sampler, " - "texcoord).x);\n" - "}"; - - GLuint vertex_shader = - CompileShader("Vertex Shader", GL_VERTEX_SHADER, vert_shader); - if (!vertex_shader) { - return 0; - } - - GLuint fragment_shader = - CompileShader("Fragment Shader", GL_FRAGMENT_SHADER, frag_shader); - if (!fragment_shader) { - gl_->DeleteShader(vertex_shader); - return 0; - } - - GLuint program = - CreateProgram("YUVConverter Program", vertex_shader, fragment_shader); - - gl_->DeleteShader(vertex_shader); - gl_->DeleteShader(fragment_shader); - - if (!program) { - return 0; - } - - gl_->UseProgram(program); - - GLint uniform_location; - uniform_location = gl_->GetUniformLocation(program, "y_sampler"); - DCHECK(uniform_location != -1); - gl_->Uniform1i(uniform_location, 0); - - uniform_location = gl_->GetUniformLocation(program, "u_sampler"); - DCHECK(uniform_location != -1); - gl_->Uniform1i(uniform_location, 1); - - uniform_location = gl_->GetUniformLocation(program, "v_sampler"); - DCHECK(uniform_location != -1); - gl_->Uniform1i(uniform_location, 2); - - uniform_location = gl_->GetUniformLocation(program, "a_sampler"); - DCHECK(uniform_location != -1); - gl_->Uniform1i(uniform_location, 3); - - gl_->UseProgram(0); - - yuv_matrix_loc_ = gl_->GetUniformLocation(program, "yuv_matrix"); - DCHECK(yuv_matrix_loc_ != -1); - - yuv_adjust_loc_ = gl_->GetUniformLocation(program, "yuv_adjust"); - DCHECK(yuv_adjust_loc_ != -1); - - return program; -} - -bool VideoDecoderShim::YUVConverter::Initialize() { - // If texture_rg extension is not available, use slower GL_LUMINANCE. - if (context_provider_->ContextCapabilities().texture_rg) { - internal_format_ = GL_RED_EXT; - format_ = GL_RED_EXT; - } else { - internal_format_ = GL_LUMINANCE; - format_ = GL_LUMINANCE; - } - - if (context_provider_->ContextCapabilities().max_texture_image_units < 4) { - // We support YUVA textures and require 4 texture units in the fragment - // stage. - return false; - } - - gl_->TraceBeginCHROMIUM("YUVConverter", "YUVConverterContext"); - gl_->GenFramebuffers(1, &frame_buffer_); - - y_texture_ = CreateTexture(); - u_texture_ = CreateTexture(); - v_texture_ = CreateTexture(); - a_texture_ = CreateTexture(); - - // Vertex positions. Also converted to texcoords in vertex shader. - GLfloat vertex_positions[] = {-1.f, -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f}; - - gl_->GenBuffers(1, &vertex_buffer_); - gl_->BindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); - gl_->BufferData(GL_ARRAY_BUFFER, 2 * sizeof(GLfloat) * 4, vertex_positions, - GL_STATIC_DRAW); - gl_->BindBuffer(GL_ARRAY_BUFFER, 0); - - program_ = CreateShader(); - - gl_->TraceEndCHROMIUM(); - - return (program_ != 0); -} - -void VideoDecoderShim::YUVConverter::Convert(const media::VideoFrame* frame, - GLuint tex_out) { - const float* yuv_matrix = nullptr; - const float* yuv_adjust = nullptr; - - if (video_format_ != frame->format()) { - // The constants below were taken from - // components/viz/service/display/gl_renderer.cc. These values are magic - // numbers that are used in the transformation from YUV to RGB color values. - // They are taken from the following webpage: - // http://www.fourcc.org/fccyvrgb.php - static const float yuv_to_rgb_rec601[9] = { - 1.164f, 1.164f, 1.164f, 0.0f, -.391f, 2.018f, 1.596f, -.813f, 0.0f, - }; - static const float yuv_to_rgb_jpeg[9] = { - 1.f, 1.f, 1.f, 0.0f, -.34414f, 1.772f, 1.402f, -.71414f, 0.0f, - }; - static const float yuv_to_rgb_rec709[9] = { - 1.164f, 1.164f, 1.164f, 0.0f, -0.213f, 2.112f, 1.793f, -0.533f, 0.0f, - }; - - // These values map to 16, 128, and 128 respectively, and are computed - // as a fraction over 256 (e.g. 16 / 256 = 0.0625). - // They are used in the YUV to RGBA conversion formula: - // Y - 16 : Gives 16 values of head and footroom for overshooting - // U - 128 : Turns unsigned U into signed U [-128,127] - // V - 128 : Turns unsigned V into signed V [-128,127] - static const float yuv_adjust_constrained[3] = { - -0.0625f, - -0.5f, - -0.5f, - }; - // Same as above, but without the head and footroom. - static const float yuv_adjust_full[3] = { - 0.0f, - -0.5f, - -0.5f, - }; - - yuv_adjust = yuv_adjust_constrained; - // TODO(hubbe): Should default to 709 - yuv_matrix = yuv_to_rgb_rec601; - - SkYUVColorSpace sk_yuv_color_space; - if (frame->ColorSpace().ToSkYUVColorSpace(&sk_yuv_color_space)) { - switch (sk_yuv_color_space) { - case kJPEG_SkYUVColorSpace: - yuv_matrix = yuv_to_rgb_jpeg; - yuv_adjust = yuv_adjust_full; - break; - case kRec709_SkYUVColorSpace: - yuv_matrix = yuv_to_rgb_rec709; - break; - case kRec601_SkYUVColorSpace: - // Current default. - break; - default: - NOTREACHED(); - } - } - - switch (frame->format()) { - case media::PIXEL_FORMAT_I420A: - case media::PIXEL_FORMAT_I420: - uv_height_divisor_ = 2; - uv_width_divisor_ = 2; - break; - case media::PIXEL_FORMAT_I422: - uv_width_divisor_ = 2; - uv_height_divisor_ = 1; - break; - case media::PIXEL_FORMAT_I444: - uv_width_divisor_ = 1; - uv_height_divisor_ = 1; - break; - - default: - NOTREACHED(); - } - - video_format_ = frame->format(); - - // Zero these so everything is reset below. - y_width_ = y_height_ = 0; - } - - gl_->TraceBeginCHROMIUM("YUVConverter", "YUVConverterContext"); - - uint32_t ywidth = frame->coded_size().width(); - uint32_t yheight = frame->coded_size().height(); - - DCHECK_EQ(frame->stride(media::VideoFrame::kUPlane), - frame->stride(media::VideoFrame::kVPlane)); - - uint32_t ystride = frame->stride(media::VideoFrame::kYPlane); - uint32_t uvstride = frame->stride(media::VideoFrame::kUPlane); - - // The following code assumes that extended GLES 2.0 state like - // UNPACK_SKIP* (if available) are set to defaults. - gl_->PixelStorei(GL_UNPACK_ALIGNMENT, 1); - - if (ywidth != y_width_ || yheight != y_height_) { - y_width_ = ywidth; - y_height_ = yheight; - - uv_width_ = y_width_ / uv_width_divisor_; - uv_height_ = y_height_ / uv_height_divisor_; - - // Re-create to resize the textures and upload data. - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, ystride); - gl_->ActiveTexture(GL_TEXTURE0); - gl_->BindTexture(GL_TEXTURE_2D, y_texture_); - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, y_width_, y_height_, 0, - format_, GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kYPlane)); - - if (video_format_ == media::PIXEL_FORMAT_I420A) { - DCHECK_EQ(frame->stride(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kAPlane)); - gl_->ActiveTexture(GL_TEXTURE3); - gl_->BindTexture(GL_TEXTURE_2D, a_texture_); - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, y_width_, y_height_, - 0, format_, GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kAPlane)); - } else { - // if there is no alpha channel, then create a 2x2 texture with full - // alpha. - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - const uint8_t alpha[4] = {0xff, 0xff, 0xff, 0xff}; - gl_->ActiveTexture(GL_TEXTURE3); - gl_->BindTexture(GL_TEXTURE_2D, a_texture_); - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, 2, 2, 0, format_, - GL_UNSIGNED_BYTE, alpha); - } - - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, uvstride); - gl_->ActiveTexture(GL_TEXTURE1); - gl_->BindTexture(GL_TEXTURE_2D, u_texture_); - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, uv_width_, uv_height_, - 0, format_, GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kUPlane)); - - gl_->ActiveTexture(GL_TEXTURE2); - gl_->BindTexture(GL_TEXTURE_2D, v_texture_); - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, uv_width_, uv_height_, - 0, format_, GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kVPlane)); - } else { - // Bind textures and upload texture data - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, ystride); - gl_->ActiveTexture(GL_TEXTURE0); - gl_->BindTexture(GL_TEXTURE_2D, y_texture_); - gl_->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, y_width_, y_height_, format_, - GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kYPlane)); - - if (video_format_ == media::PIXEL_FORMAT_I420A) { - DCHECK_EQ(frame->stride(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kAPlane)); - gl_->ActiveTexture(GL_TEXTURE3); - gl_->BindTexture(GL_TEXTURE_2D, a_texture_); - gl_->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, y_width_, y_height_, format_, - GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kAPlane)); - } else { - gl_->ActiveTexture(GL_TEXTURE3); - gl_->BindTexture(GL_TEXTURE_2D, a_texture_); - } - - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, uvstride); - gl_->ActiveTexture(GL_TEXTURE1); - gl_->BindTexture(GL_TEXTURE_2D, u_texture_); - gl_->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, uv_width_, uv_height_, format_, - GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kUPlane)); - - gl_->ActiveTexture(GL_TEXTURE2); - gl_->BindTexture(GL_TEXTURE_2D, v_texture_); - gl_->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, uv_width_, uv_height_, format_, - GL_UNSIGNED_BYTE, - frame->data(media::VideoFrame::kVPlane)); - } - - gl_->BindFramebuffer(GL_FRAMEBUFFER, frame_buffer_); - gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - tex_out, 0); - -#ifndef NDEBUG - // We should probably check for framebuffer complete here, but that - // will slow this method down so check only in debug mode. - GLint status = gl_->CheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - return; - } -#endif - - gl_->Viewport(0, 0, ywidth, yheight); - - gl_->UseProgram(program_); - - if (yuv_matrix) { - gl_->UniformMatrix3fv(yuv_matrix_loc_, 1, 0, yuv_matrix); - gl_->Uniform3fv(yuv_adjust_loc_, 1, yuv_adjust); - } - - gl_->BindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); - gl_->EnableVertexAttribArray(0); - gl_->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), - static_cast<const void*>(nullptr)); - - gl_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - // The YUVConverter shares the context with Skia and possibly other modules - // that may make OpenGL calls. To be a "good OpenGL citizen" for other - // (non-Skia) modules that may share this context we restore - // buffer/texture/state bindings to OpenGL defaults here. If we were only - // sharing the context with Skia this may not be necessary as we also - // Invalidate the GrContext below so that Skia is aware that its state - // caches need to be reset. - - gl_->BindBuffer(GL_ARRAY_BUFFER, 0); - gl_->DisableVertexAttribArray(0); - gl_->UseProgram(0); - gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); - - gl_->BindTexture(GL_TEXTURE_2D, 0); - - gl_->ActiveTexture(GL_TEXTURE2); - gl_->BindTexture(GL_TEXTURE_2D, 0); - - gl_->ActiveTexture(GL_TEXTURE1); - gl_->BindTexture(GL_TEXTURE_2D, 0); - - gl_->ActiveTexture(GL_TEXTURE0); - gl_->BindTexture(GL_TEXTURE_2D, 0); - gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - - gl_->TraceEndCHROMIUM(); -} - struct VideoDecoderShim::PendingDecode { PendingDecode(uint32_t decode_id, const scoped_refptr<media::DecoderBuffer>& buffer); @@ -817,7 +282,7 @@ void VideoDecoderShim::DecoderImpl::OnOutputComplete( DCHECK(awaiting_decoder_); std::unique_ptr<PendingFrame> pending_frame; - if (!frame->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)) + if (!frame->metadata()->end_of_stream) pending_frame.reset(new PendingFrame(decode_id_, std::move(frame))); else pending_frame.reset(new PendingFrame(decode_id_)); @@ -841,8 +306,7 @@ VideoDecoderShim::VideoDecoderShim(PepperVideoDecoderHost* host, context_provider_( RenderThreadImpl::current()->SharedMainThreadContextProvider()), texture_pool_size_(texture_pool_size), - num_pending_decodes_(0), - yuv_converter_(new YUVConverter(context_provider_)) { + num_pending_decodes_(0) { DCHECK(host_); DCHECK(media_task_runner_.get()); DCHECK(context_provider_.get()); @@ -851,11 +315,7 @@ VideoDecoderShim::VideoDecoderShim(PepperVideoDecoderHost* host, VideoDecoderShim::~VideoDecoderShim() { DCHECK(RenderThreadImpl::current()); - // Delete any remaining textures. - auto it = texture_id_map_.begin(); - for (; it != texture_id_map_.end(); ++it) - DeleteTexture(it->second); - texture_id_map_.clear(); + texture_mailbox_map_.clear(); FlushCommandBuffer(); @@ -891,9 +351,6 @@ bool VideoDecoderShim::Initialize(const Config& vda_config, Client* client) { if (!IsCodecSupported(codec)) return false; - if (!yuv_converter_->Initialize()) - return false; - media::VideoDecoderConfig video_decoder_config( codec, vda_config.profile, media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(), @@ -943,15 +400,11 @@ void VideoDecoderShim::AssignPictureBuffers( std::vector<gpu::Mailbox> mailboxes = host_->TakeMailboxes(); DCHECK_EQ(buffers.size(), mailboxes.size()); GLuint num_textures = base::checked_cast<GLuint>(buffers.size()); - std::vector<uint32_t> local_texture_ids(num_textures); - gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); for (uint32_t i = 0; i < num_textures; i++) { DCHECK_EQ(1u, buffers[i].client_texture_ids().size()); - local_texture_ids[i] = - gles2->CreateAndConsumeTextureCHROMIUM(mailboxes[i].name); - // Map the plugin texture id to the local texture id. + // Map the plugin texture id to the mailbox uint32_t plugin_texture_id = buffers[i].client_texture_ids()[0]; - texture_id_map_[plugin_texture_id] = local_texture_ids[i]; + texture_mailbox_map_[plugin_texture_id] = mailboxes[i]; available_textures_.insert(plugin_texture_id); } SendPictures(); @@ -962,7 +415,8 @@ void VideoDecoderShim::ReusePictureBuffer(int32_t picture_buffer_id) { uint32_t texture_id = static_cast<uint32_t>(picture_buffer_id); if (textures_to_dismiss_.find(texture_id) != textures_to_dismiss_.end()) { DismissTexture(texture_id); - } else if (texture_id_map_.find(texture_id) != texture_id_map_.end()) { + } else if (texture_mailbox_map_.find(texture_id) != + texture_mailbox_map_.end()) { available_textures_.insert(texture_id); SendPictures(); } else { @@ -1024,8 +478,8 @@ void VideoDecoderShim::OnOutputComplete(std::unique_ptr<PendingFrame> frame) { // If the size has changed, all current textures must be dismissed. Add // all textures to |textures_to_dismiss_| and dismiss any that aren't in // use by the plugin. We will dismiss the rest as they are recycled. - for (TextureIdMap::const_iterator it = texture_id_map_.begin(); - it != texture_id_map_.end(); ++it) { + for (IdToMailboxMap::const_iterator it = texture_mailbox_map_.begin(); + it != texture_mailbox_map_.end(); ++it) { textures_to_dismiss_.insert(it->first); } for (auto it = available_textures_.begin(); @@ -1056,10 +510,11 @@ void VideoDecoderShim::SendPictures() { uint32_t texture_id = *it; available_textures_.erase(it); - uint32_t local_texture_id = texture_id_map_[texture_id]; - - yuv_converter_->Convert(frame->video_frame.get(), local_texture_id); - + gpu::MailboxHolder destination_holder; + destination_holder.mailbox = texture_mailbox_map_[texture_id]; + destination_holder.texture_target = GL_TEXTURE_2D; + ConvertFromVideoFrameYUV(frame->video_frame.get(), context_provider_.get(), + destination_holder); host_->PictureReady(media::Picture(texture_id, frame->decode_id, frame->video_frame->visible_rect(), gfx::ColorSpace(), false)); @@ -1106,19 +561,13 @@ void VideoDecoderShim::NotifyCompletedDecodes() { void VideoDecoderShim::DismissTexture(uint32_t texture_id) { DCHECK(host_); textures_to_dismiss_.erase(texture_id); - DCHECK(texture_id_map_.find(texture_id) != texture_id_map_.end()); - DeleteTexture(texture_id_map_[texture_id]); - texture_id_map_.erase(texture_id); + DCHECK(texture_mailbox_map_.find(texture_id) != texture_mailbox_map_.end()); + texture_mailbox_map_.erase(texture_id); host_->DismissPictureBuffer(texture_id); } -void VideoDecoderShim::DeleteTexture(uint32_t texture_id) { - gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); - gles2->DeleteTextures(1, &texture_id); -} - void VideoDecoderShim::FlushCommandBuffer() { - context_provider_->ContextGL()->Flush(); + context_provider_->RasterInterface()->Flush(); } } // namespace content diff --git a/chromium/content/renderer/pepper/video_decoder_shim.h b/chromium/content/renderer/pepper/video_decoder_shim.h index bca94b97508..1edd1176a33 100644 --- a/chromium/content/renderer/pepper/video_decoder_shim.h +++ b/chromium/content/renderer/pepper/video_decoder_shim.h @@ -61,7 +61,6 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator { struct PendingDecode; struct PendingFrame; class DecoderImpl; - class YUVConverter; void OnInitializeFailed(); void OnDecodeComplete(int32_t result, uint32_t decode_id); @@ -84,9 +83,9 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator { // The current decoded frame size. gfx::Size texture_size_; - // Map that takes the plugin's GL texture id to the renderer's GL texture id. - using TextureIdMap = std::unordered_map<uint32_t, uint32_t>; - TextureIdMap texture_id_map_; + // Map that takes the plugin's GL texture id to the renderer's mailbox. + using IdToMailboxMap = std::unordered_map<uint32_t, gpu::Mailbox>; + IdToMailboxMap texture_mailbox_map_; // Available textures (these are plugin ids.) using TextureIdSet = std::unordered_set<uint32_t>; TextureIdSet available_textures_; @@ -106,8 +105,6 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator { uint32_t num_pending_decodes_; - std::unique_ptr<YUVConverter> yuv_converter_; - base::WeakPtrFactory<VideoDecoderShim> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(VideoDecoderShim); diff --git a/chromium/content/renderer/performance_manager/OWNERS b/chromium/content/renderer/performance_manager/OWNERS new file mode 100644 index 00000000000..6ef4e6df1e5 --- /dev/null +++ b/chromium/content/renderer/performance_manager/OWNERS @@ -0,0 +1 @@ +file://components/performance_manager/OWNERS diff --git a/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc new file mode 100644 index 00000000000..2cd2b9dea07 --- /dev/null +++ b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc @@ -0,0 +1,134 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h" + +#include "base/containers/flat_map.h" +#include "content/public/common/isolated_world_ids.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_local_frame_client.h" +#include "v8/include/v8.h" + +namespace performance_manager { + +namespace { + +class FrameAssociatedMeasurementDelegate : public v8::MeasureMemoryDelegate { + public: + using GetPerFrameV8MemoryUsageDataCallback = + mojom::V8PerFrameMemoryReporter::GetPerFrameV8MemoryUsageDataCallback; + + explicit FrameAssociatedMeasurementDelegate( + GetPerFrameV8MemoryUsageDataCallback&& callback) + : callback_(std::move(callback)) {} + + ~FrameAssociatedMeasurementDelegate() override { + if (callback_) { + std::move(callback_).Run(mojom::PerProcessV8MemoryUsageData::New()); + } + } + + private: + bool ShouldMeasure(v8::Local<v8::Context> context) override { + // Measure all contexts. + return true; + } + + void MeasurementComplete( + const std::vector<std::pair<v8::Local<v8::Context>, size_t>>& + context_sizes_in_bytes, + size_t unattributed_size_in_bytes) override { + mojom::PerProcessV8MemoryUsageDataPtr result = + mojom::PerProcessV8MemoryUsageData::New(); + + result->unassociated_bytes_used = unattributed_size_in_bytes; + + // Keep track of the per-frame data throughout this loop. + base::flat_map<blink::WebLocalFrame*, mojom::PerFrameV8MemoryUsageDataPtr> + frames; + for (const auto& context_and_size : context_sizes_in_bytes) { + const v8::Local<v8::Context>& context = context_and_size.first; + const size_t size = context_and_size.second; + + blink::WebLocalFrame* frame = + blink::WebLocalFrame::FrameForContext(context); + + if (!frame) { + // TODO(crbug.com/1080672): It would be prefereable to count the + // V8SchemaRegistry context's overhead with unassociated_bytes, but at + // present there isn't a public API that allows this distinction. + ++(result->num_unassociated_contexts); + result->unassociated_context_bytes_used += size; + } else { + mojom::PerFrameV8MemoryUsageData* per_frame_resources = + frames[frame].get(); + if (!per_frame_resources) { +#if DCHECK_IS_ON() + // Check that the frame token didn't already occur. + for (const auto& entry : frames) { + // This frame was already added to the map by frames[frame] above. + if (frame == entry.first) + continue; + DCHECK_NE(entry.first->GetFrameToken(), frame->GetFrameToken()); + } +#endif + auto new_resources = mojom::PerFrameV8MemoryUsageData::New(); + new_resources->frame_token = frame->GetFrameToken(); + per_frame_resources = new_resources.get(); + frames[frame] = std::move(new_resources); + } + + mojom::V8IsolatedWorldMemoryUsagePtr isolated_world_usage = + mojom::V8IsolatedWorldMemoryUsage::New(); + isolated_world_usage->bytes_used = size; + int32_t world_id = frame->GetScriptContextWorldId(context); + + if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) { + isolated_world_usage->stable_id = + frame->GetIsolatedWorldStableId(context).Utf8(); + isolated_world_usage->human_readable_name = + frame->GetIsolatedWorldHumanReadableName(context).Utf8(); + } + + DCHECK( + !base::Contains(per_frame_resources->associated_bytes, world_id)); + per_frame_resources->associated_bytes[world_id] = + std::move(isolated_world_usage); + } + } + // Move the per-frame memory values to the result. + for (auto& entry : frames) + result->associated_memory.push_back(std::move(entry.second)); + + std::move(callback_).Run(std::move(result)); + } + + GetPerFrameV8MemoryUsageDataCallback callback_; +}; + +} // namespace + +// static +void V8PerFrameMemoryReporterImpl::Create( + mojo::PendingReceiver<mojom::V8PerFrameMemoryReporter> receiver) { + mojo::MakeSelfOwnedReceiver(std::make_unique<V8PerFrameMemoryReporterImpl>(), + std::move(receiver)); +} + +void V8PerFrameMemoryReporterImpl::GetPerFrameV8MemoryUsageData( + GetPerFrameV8MemoryUsageDataCallback callback) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + if (!isolate) { + std::move(callback).Run(mojom::PerProcessV8MemoryUsageData::New()); + } else { + std::unique_ptr<FrameAssociatedMeasurementDelegate> delegate = + std::make_unique<FrameAssociatedMeasurementDelegate>( + std::move(callback)); + + isolate->MeasureMemory(std::move(delegate)); + } +} + +} // namespace performance_manager diff --git a/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h new file mode 100644 index 00000000000..8b67670b5dc --- /dev/null +++ b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h @@ -0,0 +1,24 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_PERFORMANCE_MANAGER_V8_PER_FRAME_MEMORY_REPORTER_IMPL_H_ +#define CONTENT_RENDERER_PERFORMANCE_MANAGER_V8_PER_FRAME_MEMORY_REPORTER_IMPL_H_ + +#include "content/public/common/performance_manager/v8_per_frame_memory.mojom.h" + +namespace performance_manager { + +// Exposes V8 per-frame associated memory metrics to the browser. +class V8PerFrameMemoryReporterImpl : public mojom::V8PerFrameMemoryReporter { + public: + static void Create( + mojo::PendingReceiver<mojom::V8PerFrameMemoryReporter> receiver); + + void GetPerFrameV8MemoryUsageData( + GetPerFrameV8MemoryUsageDataCallback callback) override; +}; + +} // namespace performance_manager + +#endif // CONTENT_RENDERER_PERFORMANCE_MANAGER_V8_PER_FRAME_MEMORY_REPORTER_IMPL_H_ diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc index d3461419137..74e98485b46 100644 --- a/chromium/content/renderer/render_frame_impl.cc +++ b/chromium/content/renderer/render_frame_impl.cc @@ -50,6 +50,7 @@ #include "build/build_config.h" #include "cc/base/switches.h" #include "content/common/associated_interfaces.mojom.h" +#include "content/common/ax_content_tree_update.h" #include "content/common/content_constants_internal.h" #include "content/common/content_navigation_policy.h" #include "content/common/frame.mojom.h" @@ -63,7 +64,6 @@ #include "content/common/page_messages.h" #include "content/common/render_accessibility.mojom.h" #include "content/common/renderer_host.mojom.h" -#include "content/common/savable_subframe.h" #include "content/common/unfreezable_frame_messages.h" #include "content/common/view_messages.h" #include "content/common/web_package/signed_exchange_utils.h" @@ -99,9 +99,7 @@ #include "content/renderer/gpu_benchmarking_extension.h" #include "content/renderer/history_entry.h" #include "content/renderer/history_serialization.h" -#include "content/renderer/ime_event_guard.h" #include "content/renderer/impression_conversions.h" -#include "content/renderer/input/frame_input_handler_impl.h" #include "content/renderer/input/input_target_client_impl.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/internal_document_state_data.h" @@ -112,7 +110,6 @@ #include "content/renderer/loader/web_url_loader_impl.h" #include "content/renderer/loader/web_url_request_util.h" #include "content/renderer/loader/web_worker_fetch_context_impl.h" -#include "content/renderer/low_memory_mode_controller.h" #include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/audio/audio_output_ipc_factory.h" #include "content/renderer/media/audio/audio_renderer_sink_cache.h" @@ -129,7 +126,6 @@ #include "content/renderer/render_view_impl.h" #include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/renderer_blink_platform_impl.h" -#include "content/renderer/savable_resources.h" #include "content/renderer/service_worker/service_worker_network_provider_for_frame.h" #include "content/renderer/service_worker/web_service_worker_provider_impl.h" #include "content/renderer/skia_benchmarking_extension.h" @@ -154,6 +150,7 @@ #include "ppapi/buildflags/buildflags.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h" @@ -209,6 +206,7 @@ #include "third_party/blink/public/web/web_plugin_document.h" #include "third_party/blink/public/web/web_plugin_params.h" #include "third_party/blink/public/web/web_range.h" +#include "third_party/blink/public/web/web_savable_resources_test_support.h" #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_searchable_form_data.h" #include "third_party/blink/public/web/web_security_policy.h" @@ -498,7 +496,7 @@ void FillNavigationParamsRequest( signed_exchange_utils::CreateHeaderIntegrityHashString( exchange->header_integrity)), exchange->inner_url, web_response, - std::move(exchange->loader_factory_handle).PassPipe())); + std::move(exchange->loader_factory_handle))); } } @@ -630,20 +628,51 @@ WebString ConvertRelativePathToHtmlAttribute(const base::FilePath& path) { path.NormalizePathSeparatorsTo(FILE_PATH_LITERAL('/')).AsUTF8Unsafe()); } +class RenderFrameWebFrameSerializerClient + : public blink::WebFrameSerializerClient { + public: + explicit RenderFrameWebFrameSerializerClient( + mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote) + : handler_remote_(std::move(handler_remote)) {} + + // WebFrameSerializerClient implementation: + void DidSerializeDataForFrame( + const WebVector<char>& data, + WebFrameSerializerClient::FrameSerializationStatus status) override { + DCHECK(handler_remote_.is_bound()); + handler_remote_->DidReceiveData(std::string(data.Data(), data.size())); + + // Make sure to report Done() to the browser process when receiving the last + // chunk of data, and reset the mojo remote so that the DCHECK above ensures + // this method won't be called anymore after this point. + if (status == WebFrameSerializerClient::kCurrentFrameIsFinished) { + handler_remote_->Done(); + handler_remote_.reset(); + } + } + + private: + mojo::Remote<mojom::FrameHTMLSerializerHandler> handler_remote_; +}; + // Implementation of WebFrameSerializer::LinkRewritingDelegate that responds -// based on the payload of FrameMsg_GetSerializedHtmlWithLocalLinks. +// based on the payload of mojom::Frame::GetSerializedHtmlWithLocalLinks(). class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate { public: LinkRewritingDelegate( - const std::map<GURL, base::FilePath>& url_to_local_path, - const std::map<int, base::FilePath>& frame_routing_id_to_local_path) + const base::flat_map<GURL, base::FilePath>& url_to_local_path, + const base::flat_map<base::UnguessableToken, base::FilePath>& + frame_token_to_local_path) : url_to_local_path_(url_to_local_path), - frame_routing_id_to_local_path_(frame_routing_id_to_local_path) {} + frame_token_to_local_path_(frame_token_to_local_path) {} bool RewriteFrameSource(WebFrame* frame, WebString* rewritten_link) override { - int routing_id = RenderFrame::GetRoutingIdForWebFrame(frame); - auto it = frame_routing_id_to_local_path_.find(routing_id); - if (it == frame_routing_id_to_local_path_.end()) + const base::Optional<base::UnguessableToken>& frame_token = + frame->GetFrameToken(); + + DCHECK(frame_token.has_value()); + auto it = frame_token_to_local_path_.find(frame_token.value()); + if (it == frame_token_to_local_path_.end()) return false; // This can happen because of https://crbug.com/541354. const base::FilePath& local_path = it->second; @@ -652,7 +681,7 @@ class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate { } bool RewriteLink(const WebURL& url, WebString* rewritten_link) override { - auto it = url_to_local_path_.find(url); + auto it = url_to_local_path_.find(GURL(url)); if (it == url_to_local_path_.end()) return false; @@ -662,8 +691,9 @@ class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate { } private: - const std::map<GURL, base::FilePath>& url_to_local_path_; - const std::map<int, base::FilePath>& frame_routing_id_to_local_path_; + const base::flat_map<GURL, base::FilePath>& url_to_local_path_; + const base::flat_map<base::UnguessableToken, base::FilePath>& + frame_token_to_local_path_; }; // Implementation of WebFrameSerializer::MHTMLPartsGenerationDelegate that @@ -809,17 +839,15 @@ void RecordSuffixedRendererMemoryMetrics( } mojo::PendingRemote<blink::mojom::BlobURLToken> CloneBlobURLToken( - mojo::MessagePipeHandle handle) { - if (!handle.is_valid()) + blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase>& + blob_url_token) { + if (!blob_url_token) return mojo::NullRemote(); - mojo::PendingRemote<blink::mojom::BlobURLToken> result; - mojo::Remote<blink::mojom::BlobURLToken> token( - mojo::PendingRemote<blink::mojom::BlobURLToken>( - mojo::ScopedMessagePipeHandle(handle), - blink::mojom::BlobURLToken::Version_)); - token->Clone(result.InitWithNewPipeAndPassReceiver()); - ignore_result(token.Unbind().PassPipe().release()); - return result; + mojo::PendingRemote<blink::mojom::BlobURLToken> cloned_token; + mojo::Remote<blink::mojom::BlobURLToken> token(std::move(blob_url_token)); + token->Clone(cloned_token.InitWithNewPipeAndPassReceiver()); + blob_url_token = token.Unbind(); + return cloned_token; } // Creates a fully functional DocumentState in the case where we do not have @@ -837,9 +865,7 @@ std::unique_ptr<DocumentState> BuildDocumentState() { std::unique_ptr<DocumentState> BuildDocumentStateFromParams( const mojom::CommonNavigationParams& common_params, const mojom::CommitNavigationParams& commit_params, - mojom::FrameNavigationControl::CommitNavigationCallback commit_callback, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_commit_callback, + mojom::NavigationClient::CommitNavigationCallback commit_callback, std::unique_ptr<NavigationClient> navigation_client, int request_id, bool was_initiated_in_this_frame) { @@ -868,7 +894,6 @@ std::unique_ptr<DocumentState> BuildDocumentStateFromParams( ->set_navigation_state(NavigationState::CreateBrowserInitiated( common_params.Clone(), commit_params.Clone(), std::move(commit_callback), - std::move(per_navigation_mojo_interface_commit_callback), std::move(navigation_client), was_initiated_in_this_frame)); return document_state; } @@ -986,6 +1011,9 @@ void FillMiscNavigationParams( navigation_params->force_fetch_cache_mode = blink::mojom::FetchCacheMode::kDefault; } + + navigation_params->origin_isolation_restricted = + commit_params.origin_isolation_restricted; } // Fills in the origin policy associated with this response, if any is present. @@ -1409,9 +1437,9 @@ RenderFrameImpl* RenderFrameImpl::CreateMainFrame( render_widget->InitForMainFrame(std::move(show_callback), web_frame_widget, params->visual_properties.screen_info); - // The WebFrame created here was already attached to the Page as its - // main frame, and the WebFrameWidget has been initialized, so we can call - // WebViewImpl's DidAttachLocalMainFrame(). + // The WebFrame created here was already attached to the Page as its main + // frame, and the WebFrameWidget has been initialized, so we can call + // WebView's DidAttachLocalMainFrame(). render_view->GetWebView()->DidAttachLocalMainFrame(); // The RenderWidget should start with valid VisualProperties, including a @@ -1438,7 +1466,7 @@ void RenderFrameImpl::CreateFrame( mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker, int previous_routing_id, - int opener_routing_id, + const base::UnguessableToken& opener_frame_token, int parent_routing_id, int previous_sibling_routing_id, const base::UnguessableToken& frame_token, @@ -1462,8 +1490,6 @@ void RenderFrameImpl::CreateFrame( // which would allow removing this branch altogether. See // https://crbug.com/756790. - // In https://crbug.com/1006814 we are seeing FromRoutingID return - // nullptr. This helps determine why. CHECK_NE(parent_routing_id, MSG_ROUTING_NONE); RenderFrameProxy* parent_proxy = RenderFrameProxy::FromRoutingID(parent_routing_id); @@ -1493,7 +1519,7 @@ void RenderFrameImpl::CreateFrame( previous_sibling_web_frame, frame_owner_properties->To<blink::WebFrameOwnerProperties>(), replicated_state.frame_owner_element_type, frame_token, - ResolveWebFrame(opener_routing_id)); + WebFrame::FromFrameToken(opener_frame_token)); // The RenderFrame is created and inserted into the frame tree in the above // call to createLocalChild. @@ -1583,9 +1609,9 @@ void RenderFrameImpl::CreateFrame( // TODO(crbug.com/419087): This could become part of RenderWidget Init. render_widget->OnUpdateVisualProperties(widget_params->visual_properties); - // Note that we do *not* call WebViewImpl's DidAttachLocalMainFrame() here - // for yet because this frame is provisional and not attached to the Page - // yet. We will tell WebViewImpl about it once it is swapped in. + // Note that we do *not* call WebView's DidAttachLocalMainFrame() here yet + // because this frame is provisional and not attached to the Page yet. We + // will tell WebViewImpl about it once it is swapped in. render_frame->render_widget_ = render_widget.get(); render_frame->owned_render_widget_ = std::move(render_widget); @@ -1793,10 +1819,8 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params) #endif selection_text_offset_(0), selection_range_(gfx::Range::InvalidRange()), - handling_select_range_(false), render_accessibility_manager_( std::make_unique<RenderAccessibilityManager>(this)), - is_pasting_(false), blame_context_(nullptr), #if BUILDFLAG(ENABLE_PLUGINS) focused_pepper_plugin_(nullptr), @@ -1859,12 +1883,6 @@ RenderFrameImpl::~RenderFrameImpl() { if (auto* factory = AudioOutputIPCFactory::get()) factory->MaybeDeregisterRemoteFactory(GetRoutingID()); - // |thread| may be null in tests. - if (auto* thread = RenderThreadImpl::current()) { - if (auto* controller = thread->low_memory_mode_controller()) - controller->OnFrameDestroyed(IsMainFrame()); - } - if (is_main_frame_) { // Ensure the RenderView doesn't point to this object, once it is destroyed. // TODO(nasko): Add a check that the |main_render_frame_| of |render_view_| @@ -1893,12 +1911,6 @@ void RenderFrameImpl::Initialize() { "parent", parent_id); } - // |thread| may be null in tests. - if (auto* thread = RenderThreadImpl::current()) { - if (auto* controller = thread->low_memory_mode_controller()) - controller->OnFrameCreated(IsMainFrame()); - } - #if BUILDFLAG(ENABLE_PLUGINS) new PepperBrowserConnection(this); #endif @@ -1951,6 +1963,12 @@ RenderWidget* RenderFrameImpl::GetLocalRootRenderWidget() { return GetLocalRoot()->render_widget_; } +blink::WebFrameWidget* RenderFrameImpl::GetLocalRootWebFrameWidget() { + // This is the same as GetLocalRootRenderWidget()->GetWebWidget() but + // avoids casting for type safety, woo. + return frame_->LocalRoot()->FrameWidget(); +} + RenderWidget* RenderFrameImpl::GetMainFrameRenderWidget() { RenderFrameImpl* local_main_frame = render_view()->GetMainRenderFrame(); if (!local_main_frame) @@ -1972,7 +1990,7 @@ void RenderFrameImpl::PepperDidChangeCursor(PepperPluginInstanceImpl* instance, // the plugin would like to set an invisible cursor when there isn't any user // input for a while. if (instance == pepper_last_mouse_event_target_) - GetLocalRootRenderWidget()->DidChangeCursor(cursor); + GetLocalRootRenderWidget()->GetWebWidget()->SetCursor(cursor); } void RenderFrameImpl::PepperDidReceiveMouseEvent( @@ -1999,14 +2017,14 @@ void RenderFrameImpl::PepperCancelComposition( PepperPluginInstanceImpl* instance) { if (instance != focused_pepper_plugin_) return; - if (mojom::WidgetInputHandlerHost* host = GetLocalRootRenderWidget() - ->widget_input_handler_manager() - ->GetWidgetInputHandlerHost()) { + if (blink::mojom::WidgetInputHandlerHost* host = + GetLocalRootRenderWidget() + ->widget_input_handler_manager() + ->GetWidgetInputHandlerHost()) { host->ImeCancelComposition(); } #if defined(OS_MACOSX) || defined(USE_AURA) - GetLocalRootRenderWidget()->UpdateCompositionInfo( - false /* not an immediate request */); + GetLocalRootRenderWidget()->UpdateCompositionInfo(); #endif } @@ -2025,10 +2043,6 @@ RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( if (main_frame->IsWebLocalFrame()) main_frame_url = main_frame->ToWebLocalFrame()->GetDocument().Url(); - mojo::PendingRemote<mojom::Widget> widget_channel; - mojo::PendingReceiver<mojom::Widget> widget_channel_receiver = - widget_channel.InitWithNewPipeAndPassReceiver(); - mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget; mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver = blink_widget.InitWithNewEndpointAndPassReceiver(); @@ -2041,8 +2055,8 @@ RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( // Synchronous IPC to obtain a routing id for the fullscreen widget. int32_t fullscreen_widget_routing_id = MSG_ROUTING_NONE; if (!GetFrameHost()->CreateNewFullscreenWidget( - std::move(widget_channel), std::move(blink_widget_host_receiver), - std::move(blink_widget), &fullscreen_widget_routing_id)) { + std::move(blink_widget_host_receiver), std::move(blink_widget), + &fullscreen_widget_routing_id)) { return nullptr; } RenderWidget::ShowCallback show_callback = @@ -2053,8 +2067,8 @@ RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( fullscreen_widget_routing_id, std::move(show_callback), GetLocalRootRenderWidget()->compositor_deps(), GetLocalRootRenderWidget()->GetOriginalScreenInfo(), plugin, - std::move(main_frame_url), std::move(widget_channel_receiver), - std::move(blink_widget_host), std::move(blink_widget_receiver)); + std::move(main_frame_url), std::move(blink_widget_host), + std::move(blink_widget_receiver)); // TODO(nick): The show() handshake seems like unnecessary complexity here, // since there's no real delay between CreateFullscreenWidget and // ShowCreatedFullscreenWidget. Would it be simpler to have the @@ -2079,7 +2093,7 @@ void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path, void RenderFrameImpl::SimulateImeSetComposition( const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { GetMainFrameRenderWidget()->OnImeSetComposition( @@ -2089,7 +2103,7 @@ void RenderFrameImpl::SimulateImeSetComposition( void RenderFrameImpl::SimulateImeCommitText( const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range) { GetMainFrameRenderWidget()->OnImeCommitText(text, ime_text_spans, replacement_range, 0); @@ -2097,7 +2111,7 @@ void RenderFrameImpl::SimulateImeCommitText( void RenderFrameImpl::OnImeSetComposition( const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { // When a PPAPI plugin has focus, we bypass WebKit. @@ -2187,11 +2201,6 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(FrameMsg_VisualStateRequest, OnVisualStateRequest) IPC_MESSAGE_HANDLER(FrameMsg_Reload, OnReload) - IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener) - IPC_MESSAGE_HANDLER(FrameMsg_GetSavableResourceLinks, - OnGetSavableResourceLinks) - IPC_MESSAGE_HANDLER(FrameMsg_GetSerializedHtmlWithLocalLinks, - OnGetSerializedHtmlWithLocalLinks) IPC_MESSAGE_HANDLER(FrameMsg_MixedContentFound, OnMixedContentFound) IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_Delete, OnDeleteFrame) IPC_END_MESSAGE_MAP() @@ -2212,6 +2221,16 @@ void RenderFrameImpl::OnAssociatedInterfaceRequest( } } +void RenderFrameImpl::SubmitThroughputData(ukm::SourceId source_id, + int aggregated_percent, + int impl_percent, + base::Optional<int> main_percent) { + for (auto& observer : observers_) { + observer.OnThroughputDataAvailable(source_id, aggregated_percent, + impl_percent, main_percent); + } +} + void RenderFrameImpl::BindFullscreen( mojo::PendingAssociatedReceiver<mojom::FullscreenVideoElementHandler> receiver) { @@ -2313,6 +2332,11 @@ void RenderFrameImpl::OnUnload( // For main frames, the swap should have cleared the RenderView's pointer to // this frame. CHECK(!render_view->main_render_frame_); + + // The RenderFrameProxy being swapped in here has now been attached to the + // Page as its main frame and properly initialized by the WebFrame::Swap() + // call, so we can call WebView's DidAttachRemoteMainFrame(). + render_view->GetWebView()->DidAttachRemoteMainFrame(); } if (!success) { @@ -2618,11 +2642,6 @@ void RenderFrameImpl::ForwardMessageFromHost( target_origin); } -void RenderFrameImpl::SetLifecycleState( - blink::mojom::FrameLifecycleState state) { - frame_->SetLifecycleState(state); -} - void RenderFrameImpl::UpdateBrowserControlsState( BrowserControlsState constraints, BrowserControlsState current, @@ -2662,6 +2681,21 @@ void RenderFrameImpl::SnapshotAccessibilityTree( std::move(callback).Run(response); } +void RenderFrameImpl::GetSerializedHtmlWithLocalLinks( + const base::flat_map<GURL, base::FilePath>& url_map, + const base::flat_map<base::UnguessableToken, base::FilePath>& + frame_token_map, + bool save_with_empty_url, + mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote) { + // Convert input to the canonical way of passing a map into a Blink API. + LinkRewritingDelegate delegate(url_map, frame_token_map); + RenderFrameWebFrameSerializerClient client(std::move(handler_remote)); + + // Serialize the frame (without recursing into subframes). + WebFrameSerializer::Serialize(GetWebFrame(), &client, &delegate, + save_with_empty_url); +} + #if defined(OS_ANDROID) void RenderFrameImpl::ExtractSmartClipData( const gfx::Rect& rect, @@ -2674,11 +2708,6 @@ void RenderFrameImpl::ExtractSmartClipData( } #endif // defined(OS_ANDROID) -void RenderFrameImpl::OnUpdateOpener(int opener_routing_id) { - WebFrame* opener = ResolveWebFrame(opener_routing_id); - frame_->SetOpener(opener); -} - void RenderFrameImpl::OnReload() { frame_->StartReload(WebFrameLoadType::kReload); } @@ -2759,7 +2788,7 @@ void RenderFrameImpl::CancelContextMenu(int request_id) { } void RenderFrameImpl::ShowVirtualKeyboard() { - GetLocalRootRenderWidget()->ShowVirtualKeyboard(); + GetLocalRootRenderWidget()->GetWebWidget()->ShowVirtualKeyboard(); } blink::WebPlugin* RenderFrameImpl::CreatePlugin( @@ -2911,7 +2940,7 @@ PreviewsState RenderFrameImpl::GetPreviewsState() { } bool RenderFrameImpl::IsPasting() { - return is_pasting_; + return GetLocalRootRenderWidget()->is_pasting(); } // blink::mojom::FullscreenVideoElementHandler implementation ------------------ @@ -2985,8 +3014,6 @@ void RenderFrameImpl::EnableMojoJsBindings() { enable_mojo_js_bindings_ = true; } -// mojom::FrameNavigationControl implementation -------------------------------- - void RenderFrameImpl::CommitNavigation( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, @@ -2998,79 +3025,17 @@ void RenderFrameImpl::CommitNavigation( base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory, const base::UnguessableToken& devtools_navigation_token, - CommitNavigationCallback commit_callback) { - DCHECK(!navigation_client_impl_); - // Note: We can only have FrameNavigationControl::CommitNavigation for - // non-committed interstitials where no NavigationRequest was created. - // TODO(ahemery): Remove when https://crbug.com/448486 is done. - CommitNavigationInternal( - std::move(common_params), std::move(commit_params), - std::move(response_head), std::move(response_body), - std::move(url_loader_client_endpoints), - std::move(subresource_loader_factories), std::move(subresource_overrides), - std::move(controller_service_worker_info), std::move(provider_info), - std::move(prefetch_loader_factory), devtools_navigation_token, - std::move(commit_callback), - mojom::NavigationClient::CommitNavigationCallback()); -} - -void RenderFrameImpl::CommitPerNavigationMojoInterfaceNavigation( - mojom::CommonNavigationParamsPtr common_params, - mojom::CommitNavigationParamsPtr commit_params, - network::mojom::URLResponseHeadPtr response_head, - mojo::ScopedDataPipeConsumerHandle response_body, - network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, - std::unique_ptr<blink::PendingURLLoaderFactoryBundle> - subresource_loader_factories, - base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> - subresource_overrides, - blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - prefetch_loader_factory, - const base::UnguessableToken& devtools_navigation_token, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_callback) { + mojom::NavigationClient::CommitNavigationCallback commit_callback) { DCHECK(navigation_client_impl_); - CommitNavigationInternal( - std::move(common_params), std::move(commit_params), - std::move(response_head), std::move(response_body), - std::move(url_loader_client_endpoints), - std::move(subresource_loader_factories), std::move(subresource_overrides), - std::move(controller_service_worker_info), std::move(provider_info), - std::move(prefetch_loader_factory), devtools_navigation_token, - mojom::FrameNavigationControl::CommitNavigationCallback(), - std::move(per_navigation_mojo_interface_callback)); -} - -void RenderFrameImpl::CommitNavigationInternal( - mojom::CommonNavigationParamsPtr common_params, - mojom::CommitNavigationParamsPtr commit_params, - network::mojom::URLResponseHeadPtr response_head, - mojo::ScopedDataPipeConsumerHandle response_body, - network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, - std::unique_ptr<blink::PendingURLLoaderFactoryBundle> - subresource_loader_factories, - base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> - subresource_overrides, - blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - prefetch_loader_factory, - const base::UnguessableToken& devtools_navigation_token, - mojom::FrameNavigationControl::CommitNavigationCallback callback, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_callback) { DCHECK(!IsRendererDebugURL(common_params->url)); DCHECK(!NavigationTypeUtils::IsSameDocument(common_params->navigation_type)); if (ShouldIgnoreCommitNavigation(*commit_params)) { browser_side_navigation_pending_url_ = GURL(); - AbortCommitNavigation(std::move(callback), - blink::mojom::CommitResult::Aborted); + AbortCommitNavigation(); return; } @@ -3085,8 +3050,7 @@ void RenderFrameImpl::CommitNavigationInternal( int request_id = ResourceDispatcher::MakeRequestID(); std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams( - *common_params, *commit_params, std::move(callback), - std::move(per_navigation_mojo_interface_callback), + *common_params, *commit_params, std::move(commit_callback), std::move(navigation_client_impl_), request_id, was_initiated_in_this_frame); @@ -3103,7 +3067,7 @@ void RenderFrameImpl::CommitNavigationInternal( &RenderFrameImpl::CommitNavigationWithParams, weak_factory_.GetWeakPtr(), common_params.Clone(), commit_params.Clone(), std::move(subresource_loader_factories), std::move(subresource_overrides), - std::move(controller_service_worker_info), std::move(provider_info), + std::move(controller_service_worker_info), std::move(container_info), std::move(prefetch_loader_factory), std::move(document_state)); // Perform a navigation to a data url if needed (for main frames). @@ -3196,7 +3160,7 @@ void RenderFrameImpl::CommitNavigationWithParams( base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory, std::unique_ptr<DocumentState> document_state, @@ -3285,15 +3249,15 @@ void RenderFrameImpl::CommitNavigationWithParams( navigation_params->frame_load_type = load_type; navigation_params->history_item = item_for_history_navigation; - if (!provider_info) { - // An empty provider will always be created since it is expected in a - // certain number of places. + if (!container_info) { + // An empty network provider will always be created since it is expected in + // a certain number of places. navigation_params->service_worker_network_provider = ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance(); } else { navigation_params->service_worker_network_provider = ServiceWorkerNetworkProviderForFrame::Create( - this, std::move(provider_info), + this, std::move(container_info), std::move(controller_service_worker_info), network::SharedURLLoaderFactory::Create( new_loader_factories->CloneWithoutAppCacheFactory())); @@ -3365,9 +3329,7 @@ void RenderFrameImpl::CommitFailedNavigation( if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params->url)) { // The browser expects this frame to be loading an error page. Inform it // that the load stopped. - AbortCommitNavigation( - base::NullCallback() /* deprecated interface callback */, - blink::mojom::CommitResult::Aborted); + AbortCommitNavigation(); Send(new FrameHostMsg_DidStopLoading(routing_id_)); browser_side_navigation_pending_ = false; browser_side_navigation_pending_url_ = GURL(); @@ -3394,9 +3356,7 @@ void RenderFrameImpl::CommitFailedNavigation( } if (fallback_result != blink::WebNavigationControl::NoFallbackContent) { - AbortCommitNavigation( - base::NullCallback() /* deprecated interface callback */, - blink::mojom::CommitResult::Aborted); + AbortCommitNavigation(); if (fallback_result == blink::WebNavigationControl::NoLoadInProgress) { // If the frame wasn't loading but was fallback-eligible, the fallback // content won't be shown. However, showing an error page isn't right @@ -3456,7 +3416,7 @@ void RenderFrameImpl::CommitFailedNavigation( // was not initiated through BeginNavigation, therefore // |was_initiated_in_this_frame| is false. std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams( - *common_params, *commit_params, base::NullCallback(), std::move(callback), + *common_params, *commit_params, std::move(callback), std::move(navigation_client_impl_), ResourceDispatcher::MakeRequestID(), false /* was_initiated_in_this_frame */); @@ -3477,6 +3437,8 @@ void RenderFrameImpl::CommitFailedNavigation( browser_side_navigation_pending_url_ = GURL(); } +// mojom::FrameNavigationControl implementation -------------------------------- + void RenderFrameImpl::CommitSameDocumentNavigation( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, @@ -3511,6 +3473,20 @@ void RenderFrameImpl::CommitSameDocumentNavigation( if (commit_status == blink::mojom::CommitResult::Ok) { base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); + // Same-document navigations on data URLs loaded with a valid base URL + // should keep the base URL as document URL. + bool use_base_url_for_data_url = + !common_params->base_url_for_data_url.is_empty(); +#if defined(OS_ANDROID) + use_base_url_for_data_url |= !commit_params->data_url_as_string.empty(); +#endif + + GURL url; + if (is_main_frame_ && use_base_url_for_data_url) { + url = common_params->base_url_for_data_url; + } else { + url = common_params->url; + } bool is_client_redirect = !!(common_params->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT); DocumentState* original_document_state = @@ -3523,10 +3499,8 @@ void RenderFrameImpl::CommitSameDocumentNavigation( InternalDocumentStateData::FromDocumentState(original_document_state)); // This is a browser-initiated same-document navigation (as opposed to a // fragment link click), therefore |was_initiated_in_this_frame| is false. - auto url = common_params->url; internal_data->set_navigation_state(NavigationState::CreateBrowserInitiated( std::move(common_params), std::move(commit_params), - mojom::FrameNavigationControl::CommitNavigationCallback(), mojom::NavigationClient::CommitNavigationCallback(), nullptr, false /* was_initiated_in_this_frame */)); @@ -3706,10 +3680,12 @@ RenderFrameImpl::CreateWorkerContentSettingsClient() { #if !defined(OS_ANDROID) std::unique_ptr<media::SpeechRecognitionClient> -RenderFrameImpl::CreateSpeechRecognitionClient() { +RenderFrameImpl::CreateSpeechRecognitionClient( + media::SpeechRecognitionClient::OnReadyCallback callback) { if (!frame_ || !frame_->View()) return nullptr; - return GetContentClient()->renderer()->CreateSpeechRecognitionClient(this); + return GetContentClient()->renderer()->CreateSpeechRecognitionClient( + this, std::move(callback)); } #endif @@ -3732,7 +3708,10 @@ RenderFrameImpl::CreateWorkerFetchContext() { provider->context(), render_view_->renderer_preferences(), std::move(watcher_receiver), GetLoaderFactoryBundle()->Clone(), GetLoaderFactoryBundle()->CloneWithoutAppCacheFactory(), - /*pending_subresource_loader_updater=*/mojo::NullReceiver()); + /*pending_subresource_loader_updater=*/mojo::NullReceiver(), + RenderThreadImpl::current() + ->resource_dispatcher() + ->cors_exempt_header_list()); worker_fetch_context->set_ancestor_frame_id(routing_id_); worker_fetch_context->set_frame_request_blocker(frame_request_blocker_); @@ -3959,17 +3938,6 @@ blink::WebFrame* RenderFrameImpl::FindFrame(const blink::WebString& name) { name.Utf8()); } -void RenderFrameImpl::DidChangeOpener(blink::WebFrame* opener) { - // Only a local frame should be able to update another frame's opener. - DCHECK(!opener || opener->IsWebLocalFrame()); - - int opener_routing_id = - opener ? RenderFrameImpl::FromWebFrame(opener->ToWebLocalFrame()) - ->GetRoutingID() - : MSG_ROUTING_NONE; - Send(new FrameHostMsg_DidChangeOpener(routing_id_, opener_routing_id)); -} - void RenderFrameImpl::FrameDetached(DetachType type) { for (auto& observer : observers_) observer.FrameDetached(); @@ -4044,14 +4012,6 @@ void RenderFrameImpl::DidChangeName(const blink::WebString& name) { GetFrameHost()->DidChangeName(name.Utf8(), unique_name_helper_.value()); } -void RenderFrameImpl::DidChangeFramePolicy( - blink::WebFrame* child_frame, - const blink::FramePolicy& frame_policy) { - Send(new FrameHostMsg_DidChangeFramePolicy( - routing_id_, RenderFrame::GetRoutingIdForWebFrame(child_frame), - frame_policy)); -} - void RenderFrameImpl::DidSetFramePolicyHeaders( network::mojom::WebSandboxFlags flags, const blink::ParsedFeaturePolicy& fp_header, @@ -4163,18 +4123,8 @@ void RenderFrameImpl::DidCommitNavigation( return; } - // Main frames don't require an embedding token since they aren't embedded - // in anything. Frames local to their parent also aren't considered to be - // embedded. - if (!is_main_frame_ && frame_->Parent()->IsWebRemoteFrame()) { - // Provisional frames need a new token. Non-provisional frames need one if - // they don't already have one, e.g. a crashed subframe navigating to same - // site (https://crbug.com/634368). - if (is_provisional_frame || - !GetWebFrame()->GetEmbeddingToken().has_value()) { - GetWebFrame()->SetEmbeddingToken(base::UnguessableToken::Create()); - } - } + // Generate a new embedding token on each document change. + GetWebFrame()->SetEmbeddingToken(base::UnguessableToken::Create()); // Navigations that change the document represent a new content source. Keep // track of that on the widget to help the browser process detect when stale @@ -4251,11 +4201,6 @@ void RenderFrameImpl::DidCommitNavigation( if (media_permission_dispatcher_) media_permission_dispatcher_->OnNavigation(); - if (!navigation_state->uses_per_navigation_mojo_interface()) { - navigation_state->RunCommitNavigationCallback( - blink::mojom::CommitResult::Ok); - } - ui::PageTransition transition = GetTransitionType(frame_->GetDocumentLoader(), IsMainFrame()); @@ -4275,8 +4220,7 @@ void RenderFrameImpl::DidCommitNavigation( // Check whether we have new encoding name. UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8()); - NotifyObserversOfNavigationCommit(false /* was_within_same_document */, - transition); + NotifyObserversOfNavigationCommit(transition); } void RenderFrameImpl::DidCreateInitialEmptyDocument() { @@ -4296,8 +4240,7 @@ void RenderFrameImpl::DidCommitDocumentReplacementNavigation( observer.DidCreateNewDocument(); ui::PageTransition transition = GetTransitionType(document_loader, IsMainFrame()); - NotifyObserversOfNavigationCommit(false /* was_within_same_document */, - transition); + NotifyObserversOfNavigationCommit(transition); } void RenderFrameImpl::DidClearWindowObject() { @@ -4466,8 +4409,8 @@ void RenderFrameImpl::DidFinishSameDocumentNavigation( // we don't want the transition type to persist. Just clear it. data->navigation_state()->set_transition_type(ui::PAGE_TRANSITION_LINK); - NotifyObserversOfNavigationCommit(true /* was_within_same_document */, - transition); + for (auto& observer : observers_) + observer.DidFinishSameDocumentNavigation(); } void RenderFrameImpl::DidUpdateCurrentHistoryItem() { @@ -4486,8 +4429,8 @@ void RenderFrameImpl::AbortClientNavigation() { } void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) { - if (!GetLocalRootRenderWidget()->input_handler().handling_input_event() && - !handling_select_range_) + if (!GetLocalRootRenderWidget()->GetWebWidget()->HandlingInputEvent() && + !GetLocalRootRenderWidget()->handling_select_range()) return; if (is_empty_selection) @@ -4502,21 +4445,6 @@ void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) { SyncSelectionIfRequired(); } -bool RenderFrameImpl::HandleCurrentKeyboardEvent() { - bool did_execute_command = false; - for (const auto& command : GetLocalRootRenderWidget()->edit_commands()) { - // In gtk and cocoa, it's possible to bind multiple edit commands to one - // key (but it's the exception). Once one edit command is not executed, it - // seems safest to not execute the rest. - if (!frame_->ExecuteCommand(blink::WebString::FromUTF8(command->name), - blink::WebString::FromUTF8(command->value))) - break; - did_execute_command = true; - } - - return did_execute_command; -} - void RenderFrameImpl::ShowContextMenu(const blink::WebContextMenuData& data) { UntrustworthyContextMenuParams params = ContextMenuParamsBuilder::Build(data); if (GetLocalRootRenderWidget()->has_host_context_menu_location()) { @@ -4746,10 +4674,10 @@ void RenderFrameImpl::DidChangePerformanceTiming() { } void RenderFrameImpl::DidObserveInputDelay(base::TimeDelta input_delay) { - for (auto& observer : observers_) { + for (auto& observer : observers_) observer.DidObserveInputDelay(input_delay); - } } + void RenderFrameImpl::DidChangeCpuTiming(base::TimeDelta time) { for (auto& observer : observers_) observer.DidChangeCpuTiming(time); @@ -4915,15 +4843,6 @@ void RenderFrameImpl::MarkWebAXObjectDirty(const blink::WebAXObject& obj, ->MarkWebAXObjectDirty(obj, subtree); } -void RenderFrameImpl::DidSerializeDataForFrame( - const WebVector<char>& data, - WebFrameSerializerClient::FrameSerializationStatus status) { - bool end_of_data = - status == WebFrameSerializerClient::kCurrentFrameIsFinished; - Send(new FrameHostMsg_SerializedHtmlWithLocalLinksResponse( - routing_id_, std::string(data.Data(), data.size()), end_of_data)); -} - void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) { observers_.AddObserver(observer); } @@ -5187,10 +5106,9 @@ void RenderFrameImpl::UpdateNavigationHistory( } void RenderFrameImpl::NotifyObserversOfNavigationCommit( - bool is_same_document, ui::PageTransition transition) { for (auto& observer : observers_) - observer.DidCommitProvisionalLoad(is_same_document, transition); + observer.DidCommitProvisionalLoad(transition); } void RenderFrameImpl::UpdateStateForCommit( @@ -5280,8 +5198,8 @@ void RenderFrameImpl::DidCommitNavigationInternal( } else { NavigationState* navigation_state = NavigationState::FromDocumentLoader(frame_->GetDocumentLoader()); - if (navigation_state->uses_per_navigation_mojo_interface()) { - navigation_state->RunPerNavigationInterfaceCommitNavigationCallback( + if (navigation_state->has_navigation_client()) { + navigation_state->RunCommitNavigationCallback( std::move(params), std::move(interface_params)); } else { GetFrameHost()->DidCommitProvisionalLoad(std::move(params), @@ -5354,33 +5272,16 @@ blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit( } } - // If this navigation is to a history item for a new child frame, we may - // want to ignore it if a Javascript navigation (i.e., client redirect) - // interrupted it. - // To detect this we need to check for the interrupt at different stages of - // navigation: - bool interrupted_by_client_redirect = - // IsNavigationScheduleWithin() checks that we have something just - // started, sent to the browser or loading. - (frame_->IsNavigationScheduledWithin(base::TimeDelta()) && - // The current navigation however is just returning from the browser. To - // check that it is not the current navigation, we verify the "initial - // history navigation in a subframe" flag of ClientNavigationState. - !frame_->IsClientNavigationInitialHistoryLoad()) || - // The client navigation could already have finished, in which case there - // will be an history item. - !current_history_item_.IsNull(); - if (common_params.is_history_navigation_in_new_child_frame && - interrupted_by_client_redirect) { - return blink::mojom::CommitResult::Aborted; - } + // Note: we used to check that initial history navigation in the child frame + // was not canceled by a client redirect before committing it. However, + // we now destroy the NavigationClient for initial history navigation, and + // commit does not arrive to the renderer in this case. return blink::mojom::CommitResult::Ok; } -bool RenderFrameImpl::SwapInInternal() { - CHECK_NE(previous_routing_id_, MSG_ROUTING_NONE); - CHECK(!in_frame_tree_); +const std::string& RenderFrameImpl::GetPreviousFrameUniqueName() { + DCHECK(!in_frame_tree_); RenderFrameProxy* previous_proxy = RenderFrameProxy::FromRoutingID(previous_routing_id_); @@ -5392,12 +5293,18 @@ bool RenderFrameImpl::SwapInInternal() { // the provisional frame would've been cleaned up by // RenderFrameProxy::FrameDetached. // See https://crbug.com/526304 and https://crbug.com/568676 for context. - CHECK(previous_proxy || previous_frame); - CHECK(!(previous_proxy && previous_frame)); + CHECK_NE(!!previous_proxy, !!previous_frame); - unique_name_helper_.set_propagated_name(previous_proxy - ? previous_proxy->unique_name() - : previous_frame->unique_name()); + if (previous_proxy) + return previous_proxy->unique_name(); + return previous_frame->unique_name(); +} + +bool RenderFrameImpl::SwapInInternal() { + CHECK_NE(previous_routing_id_, MSG_ROUTING_NONE); + CHECK(!in_frame_tree_); + + unique_name_helper_.set_propagated_name(GetPreviousFrameUniqueName()); // Note: Calling swap() will detach and delete |previous_frame|, so do not // reference it after this. @@ -5421,8 +5328,7 @@ bool RenderFrameImpl::SwapInInternal() { // The WebFrame being swapped in here has now been attached to the Page as // its main frame, and the WebFrameWidget was previously initialized when - // the frame was created, so we can call WebViewImpl's - // DidAttachLocalMainFrame(). + // the frame was created so we can call WebView's DidAttachLocalMainFrame(). render_view_->GetWebView()->DidAttachLocalMainFrame(); } @@ -5454,9 +5360,6 @@ void RenderFrameImpl::NotifyAccessibilityModeChange(ui::AXMode new_mode) { void RenderFrameImpl::FocusedElementChanged(const blink::WebElement& element) { has_scrolled_focused_editable_node_into_rect_ = false; - // Ensures that further text input state can be sent even when previously - // focused input and the newly focused input share the exact same state. - GetLocalRootRenderWidget()->ClearTextInputState(); for (auto& observer : observers_) observer.FocusedElementChanged(element); @@ -5624,11 +5527,11 @@ void RenderFrameImpl::BeginNavigation( if (info->navigation_policy == blink::kWebNavigationPolicyDownload) { mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token = - CloneBlobURLToken(info->blob_url_token.get()); + CloneBlobURLToken(info->blob_url_token); frame_->DownloadURL(info->url_request, network::mojom::RedirectMode::kFollow, - blob_url_token.PassPipe()); + std::move(blob_url_token)); } else { OpenURL(std::move(info)); } @@ -5645,37 +5548,6 @@ void RenderFrameImpl::CommitSyncNavigation( frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState()); } -void RenderFrameImpl::OnGetSavableResourceLinks() { - std::vector<GURL> resources_list; - std::vector<SavableSubframe> subframes; - SavableResourcesResult result(&resources_list, &subframes); - - if (!GetSavableResourceLinksForFrame(frame_, &result)) { - Send(new FrameHostMsg_SavableResourceLinksError(routing_id_)); - return; - } - - Referrer referrer = Referrer(frame_->GetDocument().Url(), - frame_->GetDocument().GetReferrerPolicy()); - - Send(new FrameHostMsg_SavableResourceLinksResponse( - routing_id_, resources_list, referrer, subframes)); -} - -void RenderFrameImpl::OnGetSerializedHtmlWithLocalLinks( - const std::map<GURL, base::FilePath>& url_to_local_path, - const std::map<int, base::FilePath>& frame_routing_id_to_local_path, - bool save_with_empty_url) { - // Convert input to the canonical way of passing a map into a Blink API. - LinkRewritingDelegate delegate(url_to_local_path, - frame_routing_id_to_local_path); - - // Serialize the frame (without recursing into subframes). - WebFrameSerializer::Serialize(GetWebFrame(), - this, // WebFrameSerializerClient. - &delegate, save_with_empty_url); -} - // mojom::MhtmlFileWriter implementation // ---------------------------------------- @@ -5788,7 +5660,8 @@ void RenderFrameImpl::OnMixedContentFound( params.request_context_type); frame_->MixedContentFound(params.main_resource_url, params.mixed_content_url, request_context, params.was_allowed, - params.had_redirect, source_location); + params.url_before_redirects, params.had_redirect, + source_location); } void RenderFrameImpl::RequestOverlayRoutingToken( @@ -5815,35 +5688,35 @@ void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info) { DCHECK(!info->url_request.RequestorOrigin().IsNull()); WebNavigationPolicy policy = info->navigation_policy; - FrameHostMsg_OpenURL_Params params; - params.url = info->url_request.Url(); - params.initiator_origin = info->url_request.RequestorOrigin(); - params.post_body = GetRequestBodyForWebURLRequest(info->url_request); - DCHECK_EQ(!!params.post_body, IsHttpPost(info->url_request)); - params.extra_headers = GetWebURLRequestHeadersAsString(info->url_request); - params.referrer.url = - blink::WebStringToGURL(info->url_request.ReferrerString()); - params.referrer.policy = info->url_request.GetReferrerPolicy(); - params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy); - params.triggering_event_info = info->triggering_event_info; - params.blob_url_token = - CloneBlobURLToken(info->blob_url_token.get()).PassPipe().release(); - params.should_replace_current_entry = + auto params = mojom::OpenURLParams::New(); + params->url = info->url_request.Url(); + params->initiator_origin = info->url_request.RequestorOrigin(); + params->post_body = GetRequestBodyForWebURLRequest(info->url_request); + DCHECK_EQ(!!params->post_body, IsHttpPost(info->url_request)); + params->extra_headers = GetWebURLRequestHeadersAsString(info->url_request); + + params->referrer = blink::mojom::Referrer::New( + blink::WebStringToGURL(info->url_request.ReferrerString()), + info->url_request.GetReferrerPolicy()); + params->disposition = RenderViewImpl::NavigationPolicyToDisposition(policy); + params->triggering_event_info = info->triggering_event_info; + params->blob_url_token = CloneBlobURLToken(info->blob_url_token).PassPipe(); + params->should_replace_current_entry = info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem && render_view_->history_list_length_; - params.user_gesture = info->has_transient_user_activation; + params->user_gesture = info->has_transient_user_activation; RenderFrameImpl* initiator_render_frame = RenderFrameImpl::FromWebFrame(info->initiator_frame); - params.initiator_routing_id = initiator_render_frame - ? initiator_render_frame->GetRoutingID() - : MSG_ROUTING_NONE; + params->initiator_routing_id = initiator_render_frame + ? initiator_render_frame->GetRoutingID() + : MSG_ROUTING_NONE; if (info->impression) - params.impression = ConvertWebImpressionToImpression(*info->impression); + params->impression = ConvertWebImpressionToImpression(*info->impression); if (GetContentClient()->renderer()->AllowPopup()) - params.user_gesture = true; + params->user_gesture = true; // A main frame navigation should already have consumed an activation in // FrameLoader::StartNavigation. @@ -5856,7 +5729,7 @@ void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info) { frame_->ConsumeTransientUserActivation(); } - params.href_translate = info->href_translate.Latin1(); + params->href_translate = info->href_translate.Latin1(); bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload(); bool has_download_sandbox_flag = @@ -5868,9 +5741,8 @@ void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info) { frame_->GetSecurityOrigin(), has_download_sandbox_flag, info->blocking_downloads_in_sandbox_enabled, - from_ad, ¶ms.download_policy); - - Send(new FrameHostMsg_OpenURL(routing_id_, params)); + from_ad, ¶ms->download_policy); + GetFrameHost()->OpenURL(std::move(params)); } ChildURLLoaderFactoryBundle* RenderFrameImpl::GetLoaderFactoryBundle() { @@ -6055,8 +5927,7 @@ void RenderFrameImpl::PrepareRenderViewForNavigation( void RenderFrameImpl::BeginNavigationInternal( std::unique_ptr<blink::WebNavigationInfo> info, bool is_history_navigation_in_new_child_frame) { - if (!frame_->WillStartNavigation(*info, - is_history_navigation_in_new_child_frame)) + if (!frame_->WillStartNavigation(*info)) return; for (auto& observer : observers_) @@ -6134,7 +6005,7 @@ void RenderFrameImpl::BeginNavigationInternal( client_side_redirect_url = frame_->GetDocument().Url(); mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token( - CloneBlobURLToken(info->blob_url_token.get())); + CloneBlobURLToken(info->blob_url_token)); int load_flags = info->url_request.GetLoadFlagsForWebUrlRequest(); std::unique_ptr<base::DictionaryValue> initiator; @@ -6232,8 +6103,8 @@ void RenderFrameImpl::SendUpdateState() { if (current_history_item_.IsNull()) return; - Send(new FrameHostMsg_UpdateState( - routing_id_, SingleHistoryItemToPageState(current_history_item_))); + GetFrameHost()->UpdateState( + SingleHistoryItemToPageState(current_history_item_)); } bool RenderFrameImpl::ShouldDisplayErrorPageForFailedLoad( @@ -6245,7 +6116,7 @@ bool RenderFrameImpl::ShouldDisplayErrorPageForFailedLoad( return false; // Don't display "client blocked" error page if browser has asked us not to. - if (error_code == net::ERR_BLOCKED_BY_CLIENT && + if (net::IsRequestBlockedError(error_code) && render_view_->renderer_preferences_.disable_client_blocked_error_page) { return false; } @@ -6329,16 +6200,10 @@ void RenderFrameImpl::RegisterMojoInterfaces() { GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( &RenderFrameImpl::BindFullscreen, weak_factory_.GetWeakPtr())); - registry_.AddInterface(base::BindRepeating( - &FrameInputHandlerImpl::CreateMojoService, weak_factory_.GetWeakPtr())); - registry_.AddInterface( base::BindRepeating(&InputTargetClientImpl::BindToReceiver, base::Unretained(&input_target_client_impl_))); - registry_.AddInterface(base::BindRepeating(&RenderFrameImpl::BindWidget, - weak_factory_.GetWeakPtr())); - GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( &RenderFrameImpl::BindMhtmlFileWriter, base::Unretained(this))); @@ -6433,10 +6298,6 @@ int RenderFrameImpl::GetEnabledBindings() { return enabled_bindings_; } -void RenderFrameImpl::FrameDidCallFocus() { - Send(new FrameHostMsg_FrameDidCallFocus(routing_id_)); -} - void RenderFrameImpl::SetAccessibilityModeForTest(ui::AXMode new_mode) { render_accessibility_manager_->SetMode(new_mode.mode()); } @@ -6456,12 +6317,6 @@ void RenderFrameImpl::SetRenderFrameMediaPlaybackOptions( renderer_media_playback_options_ = opts; } -void RenderFrameImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() { - // This is only called for web tests and WebFrameTestProxy overrides this - // method to implement it there. - NOTREACHED(); -} - void RenderFrameImpl::SetAllowsCrossBrowsingInstanceFrameLookup() { GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup(); } @@ -6576,11 +6431,6 @@ void RenderFrameImpl::RenderWidgetWillHandleMouseEvent() { #endif } -void RenderFrameImpl::BindWidget( - mojo::PendingReceiver<mojom::Widget> receiver) { - GetLocalRootRenderWidget()->SetWidgetReceiver(std::move(receiver)); -} - blink::WebComputedAXTree* RenderFrameImpl::GetOrCreateWebComputedAXTree() { if (!computed_ax_tree_) computed_ax_tree_ = std::make_unique<AomContentAxTree>(this); @@ -6612,21 +6462,11 @@ RenderFrameImpl::CreateWebSocketHandshakeThrottle() { render_frame->GetTaskRunner(blink::TaskType::kInternalDefault)); } -void RenderFrameImpl::AbortCommitNavigation( - mojom::FrameNavigationControl::CommitNavigationCallback callback, - blink::mojom::CommitResult reason) { - DCHECK(callback || navigation_client_impl_); - // The callback will trigger - // RenderFrameHostImpl::OnCrossDocumentCommitProcessed() as will the interface - // disconnection. Note: We are using the callback to determine if - // NavigationClient::CommitNavigation was used, because in certain cases we - // still use the old FrameNavigationControl path (e.g. some interstitials). - // TODO(ahemery): Update when https://crbug.com/448486 is done. - if (callback) { - std::move(callback).Run(reason); - } else { - navigation_client_impl_.reset(); - } +void RenderFrameImpl::AbortCommitNavigation() { + DCHECK(navigation_client_impl_); + // Interface disconnection will trigger + // RenderFrameHostImpl::OnCrossDocumentCommitProcessed(). + navigation_client_impl_.reset(); } void RenderFrameImpl::TransferUserActivationFrom( diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h index 0963dea51a8..c6d8de45561 100644 --- a/chromium/content/renderer/render_frame_impl.h +++ b/chromium/content/renderer/render_frame_impl.h @@ -17,7 +17,6 @@ #include <vector> #include "base/callback.h" -#include "base/containers/circular_deque.h" #include "base/containers/id_map.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" @@ -40,7 +39,6 @@ #include "content/common/render_accessibility.mojom.h" #include "content/common/renderer.mojom.h" #include "content/common/unique_name_helper.h" -#include "content/common/widget.mojom.h" #include "content/public/common/browser_controls_state.h" #include "content/public/common/fullscreen_video_element.mojom.h" #include "content/public/common/previews_state.h" @@ -59,7 +57,7 @@ #include "ipc/ipc_message.h" #include "ipc/ipc_platform_file.h" #include "media/base/routing_token_callback.h" -#include "mojo/public/cpp/bindings/associated_binding.h" +#include "media/base/speech_recognition_client.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" @@ -130,7 +128,6 @@ class WebString; class WebURL; struct FramePolicy; struct WebContextMenuData; -struct WebImeTextSpan; } // namespace blink namespace gfx { @@ -140,9 +137,6 @@ class Range; namespace media { class MediaPermission; -#if !defined(OS_ANDROID) -class SpeechRecognitionClient; -#endif } namespace service_manager { @@ -184,7 +178,6 @@ class CONTENT_EXPORT RenderFrameImpl mojom::FrameBindingsControl, mojom::MhtmlFileWriter, public blink::WebLocalFrameClient, - public blink::WebFrameSerializerClient, service_manager::mojom::InterfaceProvider { public: // Creates a new RenderFrame as the main frame of |render_view|. @@ -224,7 +217,7 @@ class CONTENT_EXPORT RenderFrameImpl mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker, int previous_routing_id, - int opener_routing_id, + const base::UnguessableToken& opener_frame_token, int parent_routing_id, int previous_sibling_routing_id, const base::UnguessableToken& frame_token, @@ -310,6 +303,9 @@ class CONTENT_EXPORT RenderFrameImpl // Returns the RenderWidget associated with this frame. RenderWidget* GetLocalRootRenderWidget(); + // Returns the blink::WebFrameWidget attached to the RenderWidget that is + // associated with this frame. + blink::WebFrameWidget* GetLocalRootWebFrameWidget(); // This method must be called after the WebLocalFrame backing this RenderFrame // has been created and added to the frame tree. It creates all objects that @@ -395,21 +391,19 @@ class CONTENT_EXPORT RenderFrameImpl // Simulates IME events for testing purpose. void SimulateImeSetComposition( const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, int selection_start, int selection_end); - void SimulateImeCommitText( - const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, - const gfx::Range& replacement_range); + void SimulateImeCommitText(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + const gfx::Range& replacement_range); // TODO(jam): remove these once the IPC handler moves from RenderView to // RenderFrame. - void OnImeSetComposition( - const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, - int selection_start, - int selection_end); + void OnImeSetComposition(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + int selection_start, + int selection_end); void OnImeCommitText(const base::string16& text, const gfx::Range& replacement_range, int relative_cursor_pos); @@ -487,7 +481,6 @@ class CONTENT_EXPORT RenderFrameImpl override; void SetRenderFrameMediaPlaybackOptions( const RenderFrameMediaPlaybackOptions& opts) override; - void UpdateAllLifecyclePhasesAndCompositeForTesting() override; void SetAllowsCrossBrowsingInstanceFrameLookup() override; gfx::RectF ElementBoundsInWindow(const blink::WebElement& element) override; void ConvertViewportToWindow(blink::WebRect* rect) override; @@ -506,13 +499,19 @@ class CONTENT_EXPORT RenderFrameImpl void BlockRequests() override; void ResumeBlockedRequests() override; void CancelBlockedRequests() override; - void SetLifecycleState(blink::mojom::FrameLifecycleState state) override; void UpdateBrowserControlsState(BrowserControlsState constraints, BrowserControlsState current, bool animate) override; void SnapshotAccessibilityTree( uint32_t ax_mode, SnapshotAccessibilityTreeCallback callback) override; + void GetSerializedHtmlWithLocalLinks( + const base::flat_map<GURL, base::FilePath>& url_map, + const base::flat_map<base::UnguessableToken, base::FilePath>& + frame_token_map, + bool save_with_empty_url, + mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote) + override; #if defined(OS_ANDROID) void ExtractSmartClipData( @@ -524,13 +523,7 @@ class CONTENT_EXPORT RenderFrameImpl void AllowBindings(int32_t enabled_bindings_flags) override; void EnableMojoJsBindings() override; - // mojom::FrameNavigationControl implementation: - void ForwardMessageFromHost( - blink::TransferableMessage message, - const url::Origin& source_origin, - const base::Optional<url::Origin>& target_origin) override; - - // mojom::FrameNavigationControl implementation: + // These mirror mojom::NavigationClient, called by NavigationClient. void CommitNavigation( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, @@ -543,35 +536,11 @@ class CONTENT_EXPORT RenderFrameImpl subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - prefetch_loader_factory, - const base::UnguessableToken& devtools_navigation_token, - mojom::FrameNavigationControl::CommitNavigationCallback commit_callback) - override; - - // This is the version to be used with PerNavigationMojoInterface enabled. - // It essentially works the same way, except the navigation callback is - // the one from NavigationClient mojo interface. - void CommitPerNavigationMojoInterfaceNavigation( - mojom::CommonNavigationParamsPtr common_params, - mojom::CommitNavigationParamsPtr commit_params, - network::mojom::URLResponseHeadPtr response_head, - mojo::ScopedDataPipeConsumerHandle response_body, - network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, - std::unique_ptr<blink::PendingURLLoaderFactoryBundle> - subresource_loader_factories, - base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> - subresource_overrides, - blink::mojom::ControllerServiceWorkerInfoPtr - controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory, const base::UnguessableToken& devtools_navigation_token, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_callback); - + mojom::NavigationClient::CommitNavigationCallback commit_callback); void CommitFailedNavigation( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, @@ -584,6 +553,7 @@ class CONTENT_EXPORT RenderFrameImpl mojom::NavigationClient::CommitFailedNavigationCallback per_navigation_mojo_interface_callback); + // mojom::FrameNavigationControl implementation: void CommitSameDocumentNavigation( mojom::CommonNavigationParamsPtr common_params, mojom::CommitNavigationParamsPtr commit_params, @@ -596,7 +566,6 @@ class CONTENT_EXPORT RenderFrameImpl mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host, mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver) override; - void JavaScriptExecuteRequest( const base::string16& javascript, bool wants_result, @@ -612,6 +581,10 @@ class CONTENT_EXPORT RenderFrameImpl bool wants_result, int32_t world_id, JavaScriptExecuteRequestInIsolatedWorldCallback callback) override; + void ForwardMessageFromHost( + blink::TransferableMessage message, + const url::Origin& source_origin, + const base::Optional<url::Origin>& target_origin) override; void OnPortalActivated( const base::UnguessableToken& portal_token, mojo::PendingAssociatedRemote<blink::mojom::Portal> portal, @@ -640,8 +613,8 @@ class CONTENT_EXPORT RenderFrameImpl std::unique_ptr<blink::WebContentSettingsClient> CreateWorkerContentSettingsClient() override; #if !defined(OS_ANDROID) - std::unique_ptr<media::SpeechRecognitionClient> - CreateSpeechRecognitionClient(); + std::unique_ptr<media::SpeechRecognitionClient> CreateSpeechRecognitionClient( + media::SpeechRecognitionClient::OnReadyCallback callback) override; #endif scoped_refptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext() override; @@ -673,11 +646,8 @@ class CONTENT_EXPORT RenderFrameImpl const base::UnguessableToken& portal_token, const blink::WebElement& portal_element) override; blink::WebFrame* FindFrame(const blink::WebString& name) override; - void DidChangeOpener(blink::WebFrame* frame) override; void FrameDetached(DetachType type) override; void DidChangeName(const blink::WebString& name) override; - void DidChangeFramePolicy(blink::WebFrame* child_frame, - const blink::FramePolicy& frame_policy) override; void DidSetFramePolicyHeaders( network::mojom::WebSandboxFlags flags, const blink::ParsedFeaturePolicy& fp_header, @@ -719,7 +689,6 @@ class CONTENT_EXPORT RenderFrameImpl base::UnguessableToken GetDevToolsFrameToken() override; void AbortClientNavigation() override; void DidChangeSelection(bool is_empty_selection) override; - bool HandleCurrentKeyboardEvent() override; void ShowContextMenu(const blink::WebContextMenuData& data) override; void FrameRectsChanged(const blink::WebRect& frame_rect) override; void FocusedElementChanged(const blink::WebElement& element) override; @@ -771,12 +740,10 @@ class CONTENT_EXPORT RenderFrameImpl void OnStopLoading() override; void DraggableRegionsChanged() override; blink::BrowserInterfaceBrokerProxy* GetBrowserInterfaceBroker() override; - - // WebFrameSerializerClient implementation: - void DidSerializeDataForFrame( - const blink::WebVector<char>& data, - blink::WebFrameSerializerClient::FrameSerializationStatus status) - override; + void SubmitThroughputData(ukm::SourceId source_id, + int aggregated_percent, + int impl_percent, + base::Optional<int> main_percent) override; // Binds to the fullscreen service in the browser. void BindFullscreen( @@ -838,12 +805,6 @@ class CONTENT_EXPORT RenderFrameImpl void NotifyObserversOfFailedProvisionalLoad(); - bool handling_select_range() const { return handling_select_range_; } - - void set_is_pasting(bool value) { is_pasting_ = value; } - - void set_handling_select_range(bool value) { handling_select_range_ = value; } - // Plugin-related functions -------------------------------------------------- #if BUILDFLAG(ENABLE_PLUGINS) @@ -889,10 +850,6 @@ class CONTENT_EXPORT RenderFrameImpl void ScrollFocusedEditableElementIntoRect(const gfx::Rect& rect); void ResetHasScrolledFocusedEditableIntoView(); - // Called to notify a frame that it called |window.focus()| on a different - // frame. - void FrameDidCallFocus(); - // Called when an ongoing renderer-initiated navigation was dropped by the // browser. void OnDroppedNavigation(); @@ -922,6 +879,11 @@ class CONTENT_EXPORT RenderFrameImpl bool IsLocalRoot() const; const RenderFrameImpl* GetLocalRoot() const; + // Gets the unique_name() of the frame being replaced by this frame, when + // it is a provisional frame. Invalid to call on frames that are already + // attached to the frame tree. + const std::string& GetPreviousFrameUniqueName(); + private: friend class RenderFrameImplTest; friend class RenderFrameObserver; @@ -1039,12 +1001,6 @@ class CONTENT_EXPORT RenderFrameImpl void OnVisualStateRequest(uint64_t key); // TODO(https://crbug.com/995428): Deprecated. void OnReload(); - void OnUpdateOpener(int opener_routing_id); - void OnGetSavableResourceLinks(); - void OnGetSerializedHtmlWithLocalLinks( - const std::map<GURL, base::FilePath>& url_to_local_path, - const std::map<int, base::FilePath>& frame_routing_id_to_local_path, - bool save_with_empty_url); void OnSuppressFurtherDialogs(); void OnMixedContentFound(const FrameMsg_MixedContentFound_Params& params); @@ -1123,7 +1079,7 @@ class CONTENT_EXPORT RenderFrameImpl subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory, std::unique_ptr<DocumentState> document_state, @@ -1170,8 +1126,6 @@ class CONTENT_EXPORT RenderFrameImpl // call |callback| before returning. void RequestOverlayRoutingToken(media::RoutingTokenCallback callback); - void BindWidget(mojo::PendingReceiver<mojom::Widget> receiver); - void ShowDeferredContextMenu(const UntrustworthyContextMenuParams& params); // Build DidCommitProvisionalLoad_Params based on the frame internal state. @@ -1189,8 +1143,7 @@ class CONTENT_EXPORT RenderFrameImpl blink::WebHistoryCommitType commit_type); // Notify render_view_ observers that a commit happened. - void NotifyObserversOfNavigationCommit(bool is_same_document, - ui::PageTransition transition); + void NotifyObserversOfNavigationCommit(ui::PageTransition transition); // Updates the internal state following a navigation commit. This should be // called before notifying the FrameHost of the commit. @@ -1263,35 +1216,11 @@ class CONTENT_EXPORT RenderFrameImpl blink::WebHistoryItem* item_for_history_navigation, blink::WebFrameLoadType* load_type); - // These functions avoid duplication between Commit*Navigation and - // Commit*PerNavigationMojoInterfaceNavigation functions. - void CommitNavigationInternal( - mojom::CommonNavigationParamsPtr common_params, - mojom::CommitNavigationParamsPtr commit_params, - network::mojom::URLResponseHeadPtr response_head, - mojo::ScopedDataPipeConsumerHandle response_body, - network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, - std::unique_ptr<blink::PendingURLLoaderFactoryBundle> - subresource_loader_factories, - base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> - subresource_overrides, - blink::mojom::ControllerServiceWorkerInfoPtr - controller_service_worker_info, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - prefetch_loader_factory, - const base::UnguessableToken& devtools_navigation_token, - mojom::FrameNavigationControl::CommitNavigationCallback callback, - mojom::NavigationClient::CommitNavigationCallback - per_navigation_mojo_interface_callback); - // Ignores the navigation commit and stop its processing in the RenderFrame. // This will drop the NavigationRequest in the RenderFrameHost. // Note: This is only meant to be used before building the DocumentState. // Commit abort and navigation end is handled by it afterwards. - void AbortCommitNavigation( - mojom::FrameNavigationControl::CommitNavigationCallback callback, - blink::mojom::CommitResult reason); + void AbortCommitNavigation(); // Implements AddMessageToConsole(). void AddMessageToConsoleImpl(blink::mojom::ConsoleMessageLevel level, @@ -1418,9 +1347,6 @@ class CONTENT_EXPORT RenderFrameImpl // Range over the document corresponding to the actual selected text (which // could correspond to a substring of |selection_text_|; see above). gfx::Range selection_range_; - // Used to inform didChangeSelection() when it is called in the context - // of handling a FrameInputHandler::SelectRange IPC. - bool handling_select_range_; // Implements getUserMedia() and related functionality. std::unique_ptr<blink::WebMediaStreamDeviceObserver> @@ -1441,9 +1367,6 @@ class CONTENT_EXPORT RenderFrameImpl // Valid during the entire life time of the RenderFrame. std::unique_ptr<RenderAccessibilityManager> render_accessibility_manager_; - // Whether or not this RenderFrame is currently pasting. - bool is_pasting_; - std::unique_ptr<FrameBlameContext> blame_context_; // Plugins ------------------------------------------------------------------- diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc index 866a4905895..ec4bbb47959 100644 --- a/chromium/content/renderer/render_frame_impl_browsertest.cc +++ b/chromium/content/renderer/render_frame_impl_browsertest.cc @@ -128,7 +128,7 @@ class RenderFrameImplTest : public RenderViewTest { RenderFrameImpl::CreateFrame( kSubframeRouteId, std::move(stub_interface_provider), std::move(stub_browser_interface_broker), MSG_ROUTING_NONE, - MSG_ROUTING_NONE, kFrameProxyRouteId, MSG_ROUTING_NONE, + base::UnguessableToken(), kFrameProxyRouteId, MSG_ROUTING_NONE, base::UnguessableToken::Create(), base::UnguessableToken::Create(), frame_replication_state, &compositor_deps_, std::move(widget_params), blink::mojom::FrameOwnerProperties::New(), @@ -379,17 +379,15 @@ TEST_F(RenderViewImplDownloadURLTest, DownloadUrlLimit) { EXPECT_CALL(*download_url_mock_local_frame_host(), DownloadURL(testing::_)) .Times(10); for (int i = 0; i < 10; ++i) { - frame()->GetWebFrame()->DownloadURL(request, - network::mojom::RedirectMode::kManual, - mojo::ScopedMessagePipeHandle()); + frame()->GetWebFrame()->DownloadURL( + request, network::mojom::RedirectMode::kManual, mojo::NullRemote()); base::RunLoop().RunUntilIdle(); } EXPECT_CALL(*download_url_mock_local_frame_host(), DownloadURL(testing::_)) .Times(0); - frame()->GetWebFrame()->DownloadURL(request, - network::mojom::RedirectMode::kManual, - mojo::ScopedMessagePipeHandle()); + frame()->GetWebFrame()->DownloadURL( + request, network::mojom::RedirectMode::kManual, mojo::NullRemote()); base::RunLoop().RunUntilIdle(); } @@ -399,7 +397,7 @@ TEST_F(RenderViewImplDownloadURLTest, DownloadUrlLimit) { TEST_F(RenderFrameImplTest, NoCrashWhenDeletingFrameDuringFind) { frame()->GetWebFrame()->FindForTesting( 1, "foo", true /* match_case */, true /* forward */, - false /* find_next */, true /* force */, false /* wrap_within_frame */); + true /* new_session */, true /* force */, false /* wrap_within_frame */); UnfreezableFrameMsg_Delete delete_message( 0, FrameDeleteIntention::kNotMainFrame); @@ -725,11 +723,12 @@ class FrameHostTestInterfaceRequestIssuer : public RenderFrameObserver { RequestTestInterfaceOnFrameEvent(kFrameEventReadyToCommitNavigation); } - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override { - RequestTestInterfaceOnFrameEvent(is_same_document_navigation - ? kFrameEventDidCommitSameDocumentLoad - : kFrameEventDidCommitProvisionalLoad); + void DidCommitProvisionalLoad(ui::PageTransition transition) override { + RequestTestInterfaceOnFrameEvent(kFrameEventDidCommitProvisionalLoad); + } + + void DidFinishSameDocumentNavigation() override { + RequestTestInterfaceOnFrameEvent(kFrameEventDidCommitSameDocumentLoad); } DISALLOW_COPY_AND_ASSIGN(FrameHostTestInterfaceRequestIssuer); @@ -751,8 +750,7 @@ class FrameCommitWaiter : public RenderFrameObserver { // RenderFrameObserver: void OnDestruct() override {} - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override { + void DidCommitProvisionalLoad(ui::PageTransition transition) override { did_commit_ = true; run_loop_.Quit(); } diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl.cc b/chromium/content/renderer/render_frame_metadata_observer_impl.cc index 9c118ebbd51..0f940818f21 100644 --- a/chromium/content/renderer/render_frame_metadata_observer_impl.cc +++ b/chromium/content/renderer/render_frame_metadata_observer_impl.cc @@ -58,10 +58,19 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission( send_metadata |= force_send; } - // Allways cache the full metadata, so that it can correctly be sent upon - // ReportAllFrameSubmissionsForTesting or - // ReportAllRootScrollsForAccessibility. This must only be done after we've - // compared the two for changes. +#if defined(OS_ANDROID) + const bool send_root_scroll_offset_changed = + report_all_root_scrolls_enabled_ && !send_metadata && + render_frame_metadata_observer_client_ && last_render_frame_metadata_ && + last_render_frame_metadata_->root_scroll_offset != + render_frame_metadata.root_scroll_offset && + render_frame_metadata.root_scroll_offset.has_value(); +#endif + + // Always cache the full metadata, so that it can correctly be sent upon + // ReportAllFrameSubmissionsForTesting or on android, which notifies on any + // root scroll offset change. This must only be done after we've compared the + // two for changes. last_render_frame_metadata_ = render_frame_metadata; // If the metadata is different, updates all the observers; or the metadata is @@ -99,6 +108,13 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission( : "null"); } +#if defined(OS_ANDROID) + if (send_root_scroll_offset_changed) { + render_frame_metadata_observer_client_->OnRootScrollOffsetChanged( + *render_frame_metadata.root_scroll_offset); + } +#endif + // Always cache the initial frame token, so that if a test connects later on // it can be notified of the initial state. if (!last_frame_token_) { @@ -109,9 +125,8 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission( } #if defined(OS_ANDROID) -void RenderFrameMetadataObserverImpl::ReportAllRootScrollsForAccessibility( - bool enabled) { - report_all_root_scrolls_for_accessibility_enabled_ = enabled; +void RenderFrameMetadataObserverImpl::ReportAllRootScrolls(bool enabled) { + report_all_root_scrolls_enabled_ = enabled; if (enabled) SendLastRenderFrameMetadata(); @@ -147,6 +162,7 @@ bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata( rfm1.page_scale_factor != rfm2.page_scale_factor || rfm1.external_page_scale_factor != rfm2.external_page_scale_factor || rfm1.is_mobile_optimized != rfm2.is_mobile_optimized || + rfm1.has_delegated_ink_metadata != rfm2.has_delegated_ink_metadata || rfm1.device_scale_factor != rfm2.device_scale_factor || rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels || rfm1.top_controls_height != rfm2.top_controls_height || @@ -159,9 +175,6 @@ bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata( } #if defined(OS_ANDROID) - bool need_send_root_scroll = - report_all_root_scrolls_for_accessibility_enabled_ && - rfm1.root_scroll_offset != rfm2.root_scroll_offset; if (rfm1.bottom_controls_height != rfm2.bottom_controls_height || rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio || rfm1.top_controls_min_height_offset != @@ -173,8 +186,7 @@ bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata( rfm1.root_overflow_y_hidden != rfm2.root_overflow_y_hidden || rfm1.scrollable_viewport_size != rfm2.scrollable_viewport_size || rfm1.root_layer_size != rfm2.root_layer_size || - rfm1.has_transparent_background != rfm2.has_transparent_background || - need_send_root_scroll) { + rfm1.has_transparent_background != rfm2.has_transparent_background) { *needs_activation_notification = true; return true; } diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl.h b/chromium/content/renderer/render_frame_metadata_observer_impl.h index f253f7b82bd..8186274aff4 100644 --- a/chromium/content/renderer/render_frame_metadata_observer_impl.h +++ b/chromium/content/renderer/render_frame_metadata_observer_impl.h @@ -45,7 +45,7 @@ class CONTENT_EXPORT RenderFrameMetadataObserverImpl // mojom::RenderFrameMetadataObserver: #if defined(OS_ANDROID) - void ReportAllRootScrollsForAccessibility(bool enabled) override; + void ReportAllRootScrolls(bool enabled) override; #endif void ReportAllFrameSubmissionsForTesting(bool enabled) override; @@ -67,7 +67,7 @@ class CONTENT_EXPORT RenderFrameMetadataObserverImpl #if defined(OS_ANDROID) // When true this will notify |render_frame_metadata_observer_client_| of all // frame submissions that involve a root scroll offset change. - bool report_all_root_scrolls_for_accessibility_enabled_ = false; + bool report_all_root_scrolls_enabled_ = false; #endif // When true this will notify |render_frame_metadata_observer_client_| of all diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc b/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc index cf19f246a6a..28f2302b864 100644 --- a/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc +++ b/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc @@ -42,6 +42,9 @@ class MockRenderFrameMetadataObserverClient void(uint32_t frame_token, const cc::RenderFrameMetadata& metadata)); MOCK_METHOD1(OnFrameSubmissionForTesting, void(uint32_t frame_token)); +#if defined(OS_ANDROID) + MOCK_METHOD1(OnRootScrollOffsetChanged, void(const gfx::Vector2dF& offset)); +#endif private: mojo::Receiver<mojom::RenderFrameMetadataObserverClient> @@ -207,7 +210,7 @@ TEST_F(RenderFrameMetadataObserverImplTest, SendRootScrollsForAccessibility) { // Enable reporting for root scroll changes. This will generate one // notification. - observer_impl().ReportAllRootScrollsForAccessibility(true); + observer_impl().ReportAllRootScrolls(true); { base::RunLoop run_loop; EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token, @@ -223,10 +226,8 @@ TEST_F(RenderFrameMetadataObserverImplTest, SendRootScrollsForAccessibility) { false /* force_send */); { base::RunLoop run_loop; - // The 0u frame token indicates that the client should not expect - // a corresponding frame token from Viz. - EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token, - render_frame_metadata)) + EXPECT_CALL(client(), OnRootScrollOffsetChanged( + *(render_frame_metadata.root_scroll_offset))) .WillOnce(InvokeClosure(run_loop.QuitClosure())); run_loop.Run(); } diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc index fb083b2f555..a157e2cdacc 100644 --- a/chromium/content/renderer/render_frame_proxy.cc +++ b/chromium/content/renderer/render_frame_proxy.cc @@ -115,10 +115,11 @@ RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame( return proxy.release(); } +// static RenderFrameProxy* RenderFrameProxy::CreateFrameProxy( int routing_id, int render_view_routing_id, - blink::WebFrame* opener, + const base::UnguessableToken& opener_frame_token, int parent_routing_id, const FrameReplicationState& replicated_state, const base::UnguessableToken& frame_token, @@ -139,14 +140,19 @@ RenderFrameProxy* RenderFrameProxy::CreateFrameProxy( RenderWidget* ancestor_widget = nullptr; blink::WebRemoteFrame* web_frame = nullptr; + auto* opener = blink::WebFrame::FromFrameToken(opener_frame_token); if (!parent) { // Create a top level WebRemoteFrame. render_view = RenderViewImpl::FromRoutingID(render_view_routing_id); + blink::WebView* web_view = render_view->GetWebView(); web_frame = blink::WebRemoteFrame::CreateMainFrame( - render_view->GetWebView(), proxy.get(), - proxy->blink_interface_registry_.get(), + web_view, proxy.get(), proxy->blink_interface_registry_.get(), proxy->GetRemoteAssociatedInterfaces(), frame_token, opener); // Root frame proxy has no ancestors to point to their RenderWidget. + + // The WebRemoteFrame created here was already attached to the Page as its + // main frame, so we can call WebView's DidAttachRemoteMainFrame(). + web_view->DidAttachRemoteMainFrame(); } else { // Create a frame under an existing parent. The parent is always expected // to be a RenderFrameProxy, because navigations initiated by local frames @@ -301,6 +307,13 @@ void RenderFrameProxy::OnZoomLevelChanged(double zoom_level) { SynchronizeVisualProperties(); } +void RenderFrameProxy::OnRootWindowSegmentsChanged( + std::vector<gfx::Rect> root_widget_window_segments) { + pending_visual_properties_.root_widget_window_segments = + std::move(root_widget_window_segments); + SynchronizeVisualProperties(); +} + void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor, bool is_pinch_gesture_active) { DCHECK(ancestor_render_widget_); @@ -359,7 +372,10 @@ void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) { web_frame_->SetReplicatedAdFrameType(state.ad_frame_type); web_frame_->SetReplicatedFeaturePolicyHeaderAndOpenerPolicies( state.feature_policy_header, state.opener_feature_state); - if (state.has_received_user_gesture) { + if (state.has_active_user_gesture) { + // TODO(crbug.com/1087963): This should be hearing about sticky activations + // and setting those (as well as the active one?). But the call to + // UpdateUserActivationState sets the transient activation. web_frame_->UpdateUserActivationState( blink::mojom::UserActivationUpdateType::kNotifyActivation); } @@ -387,10 +403,7 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg) - IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener) IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateName, OnDidUpdateName) - IPC_MESSAGE_HANDLER(FrameMsg_TransferUserActivationFrom, - OnTransferUserActivationFrom) IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_DeleteProxy, OnDeleteProxy) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -426,11 +439,6 @@ void RenderFrameProxy::ChildProcessGone() { screen_info().device_scale_factor); } -void RenderFrameProxy::OnUpdateOpener(int opener_routing_id) { - blink::WebFrame* opener = RenderFrameImpl::ResolveWebFrame(opener_routing_id); - web_frame_->SetOpener(opener); -} - void RenderFrameProxy::DidStartLoading() { web_frame_->DidStartLoading(); } @@ -441,14 +449,6 @@ void RenderFrameProxy::OnDidUpdateName(const std::string& name, unique_name_ = unique_name; } -void RenderFrameProxy::OnTransferUserActivationFrom(int32_t source_routing_id) { - RenderFrameProxy* source_proxy = - RenderFrameProxy::FromRoutingID(source_routing_id); - if (!source_proxy) - return; - web_frame()->TransferUserActivationFrom(source_proxy->web_frame()); -} - void RenderFrameProxy::DidUpdateVisualProperties( const cc::RenderFrameMetadata& metadata) { if (!parent_local_surface_id_allocator_->UpdateFromChild( @@ -527,6 +527,8 @@ void RenderFrameProxy::SynchronizeVisualProperties() { pending_visual_properties_.visible_viewport_size || sent_visual_properties_->compositor_viewport != pending_visual_properties_.compositor_viewport || + sent_visual_properties_->root_widget_window_segments != + pending_visual_properties_.root_widget_window_segments || capture_sequence_number_changed; if (synchronized_props_changed) { @@ -606,34 +608,6 @@ void RenderFrameProxy::FrameDetached(DetachType type) { delete this; } -void RenderFrameProxy::ForwardPostMessage( - blink::WebLocalFrame* source_frame, - blink::WebRemoteFrame* target_frame, - blink::WebSecurityOrigin target_origin, - blink::WebDOMMessageEvent event) { - DCHECK(!web_frame_ || web_frame_ == target_frame); - - FrameMsg_PostMessage_Params params; - params.message = - new base::RefCountedData<blink::TransferableMessage>(event.AsMessage()); - params.source_origin = event.Origin().Utf16(); - if (!target_origin.IsNull()) - params.target_origin = target_origin.ToString().Utf16(); - - // Include the routing ID for the source frame (if one exists), which the - // browser process will translate into the routing ID for the equivalent - // frame in the target process. - params.source_routing_id = MSG_ROUTING_NONE; - if (source_frame) { - RenderFrameImpl* source_render_frame = - RenderFrameImpl::FromWebFrame(source_frame); - if (source_render_frame) - params.source_routing_id = source_render_frame->GetRoutingID(); - } - - Send(new FrameHostMsg_RouteMessageEvent(routing_id_, params)); -} - void RenderFrameProxy::Navigate( const blink::WebURLRequest& request, blink::WebLocalFrame* initiator_frame, @@ -642,33 +616,37 @@ void RenderFrameProxy::Navigate( bool initiator_frame_has_download_sandbox_flag, bool blocking_downloads_in_sandbox_enabled, bool initiator_frame_is_ad, - mojo::ScopedMessagePipeHandle blob_url_token, + blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase> + blob_url_token, const base::Optional<blink::WebImpression>& impression) { // The request must always have a valid initiator origin. DCHECK(!request.RequestorOrigin().IsNull()); - FrameHostMsg_OpenURL_Params params; - params.url = request.Url(); - params.initiator_origin = request.RequestorOrigin(); - params.post_body = GetRequestBodyForWebURLRequest(request); - DCHECK_EQ(!!params.post_body, request.HttpMethod().Utf8() == "POST"); - params.extra_headers = GetWebURLRequestHeadersAsString(request); - params.referrer.url = blink::WebStringToGURL(request.ReferrerString()); - params.referrer.policy = request.GetReferrerPolicy(); - params.disposition = WindowOpenDisposition::CURRENT_TAB; - params.should_replace_current_entry = should_replace_current_entry; - params.user_gesture = request.HasUserGesture(); - params.triggering_event_info = blink::TriggeringEventInfo::kUnknown; - params.blob_url_token = blob_url_token.release(); + auto params = mojom::OpenURLParams::New(); + params->url = request.Url(); + params->initiator_origin = request.RequestorOrigin(); + params->post_body = GetRequestBodyForWebURLRequest(request); + DCHECK_EQ(!!params->post_body, request.HttpMethod().Utf8() == "POST"); + params->extra_headers = GetWebURLRequestHeadersAsString(request); + params->referrer = blink::mojom::Referrer::New( + blink::WebStringToGURL(request.ReferrerString()), + request.GetReferrerPolicy()); + params->disposition = WindowOpenDisposition::CURRENT_TAB; + params->should_replace_current_entry = should_replace_current_entry; + params->user_gesture = request.HasUserGesture(); + params->triggering_event_info = blink::TriggeringEventInfo::kUnknown; + params->blob_url_token = + mojo::PendingRemote<blink::mojom::BlobURLToken>(std::move(blob_url_token)) + .PassPipe(); RenderFrameImpl* initiator_render_frame = RenderFrameImpl::FromWebFrame(initiator_frame); - params.initiator_routing_id = initiator_render_frame - ? initiator_render_frame->GetRoutingID() - : MSG_ROUTING_NONE; + params->initiator_routing_id = initiator_render_frame + ? initiator_render_frame->GetRoutingID() + : MSG_ROUTING_NONE; if (impression) - params.impression = ConvertWebImpressionToImpression(*impression); + params->impression = ConvertWebImpressionToImpression(*impression); // Note: For the AdFrame/Sandbox download policy here it only covers the case // where the navigation initiator frame is ad. The download_policy may be @@ -678,9 +656,9 @@ void RenderFrameProxy::Navigate( is_opener_navigation, request, web_frame_->GetSecurityOrigin(), initiator_frame_has_download_sandbox_flag, blocking_downloads_in_sandbox_enabled, initiator_frame_is_ad, - ¶ms.download_policy); + ¶ms->download_policy); - Send(new FrameHostMsg_OpenURL(routing_id_, params)); + GetFrameProxyHost()->OpenURL(std::move(params)); } void RenderFrameProxy::FrameRectsChanged( @@ -716,28 +694,6 @@ void RenderFrameProxy::UpdateRemoteViewportIntersection( intersection_state)); } -void RenderFrameProxy::DidChangeOpener(blink::WebFrame* opener) { - // A proxy shouldn't normally be disowning its opener. It is possible to get - // here when a proxy that is being detached clears its opener, in which case - // there is no need to notify the browser process. - if (!opener) - return; - - // Only a LocalFrame (i.e., the caller of window.open) should be able to - // update another frame's opener. - DCHECK(opener->IsWebLocalFrame()); - - int opener_routing_id = - RenderFrameImpl::FromWebFrame(opener->ToWebLocalFrame())->GetRoutingID(); - Send(new FrameHostMsg_DidChangeOpener(routing_id_, opener_routing_id)); -} - -void RenderFrameProxy::AdvanceFocus(blink::mojom::FocusType type, - blink::WebLocalFrame* source) { - int source_routing_id = RenderFrameImpl::FromWebFrame(source)->GetRoutingID(); - Send(new FrameHostMsg_AdvanceFocus(routing_id_, type, source_routing_id)); -} - base::UnguessableToken RenderFrameProxy::GetDevToolsFrameToken() { return devtools_frame_token_; } @@ -749,9 +705,18 @@ cc::Layer* RenderFrameProxy::GetLayer() { void RenderFrameProxy::SetLayer(scoped_refptr<cc::Layer> layer, bool prevent_contents_opaque_changes, bool is_surface_layer) { + // |ancestor_render_widget_| can be null if this is a proxy for a remote main + // frame, or a subframe of that proxy. However, we should not be setting a + // layer on such a proxy (the layer is used for embedding a child proxy). + DCHECK(ancestor_render_widget_); + if (web_frame()) { web_frame()->SetCcLayer(layer.get(), prevent_contents_opaque_changes, is_surface_layer); + + // Schedule an animation so that a new frame is produced with the updated + // layer, otherwise this local root's visible content may not be up to date. + ancestor_render_widget_->ScheduleAnimation(); } embedded_layer_ = std::move(layer); } diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h index 6012fd36b03..5aa6af9bd8c 100644 --- a/chromium/content/renderer/render_frame_proxy.h +++ b/chromium/content/renderer/render_frame_proxy.h @@ -97,7 +97,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, static RenderFrameProxy* CreateFrameProxy( int routing_id, int render_view_routing_id, - blink::WebFrame* opener, + const base::UnguessableToken& opener_frame_token, int parent_routing_id, const FrameReplicationState& replicated_state, const base::UnguessableToken& frame_token, @@ -139,6 +139,8 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, // a result. void OnScreenInfoChanged(const ScreenInfo& screen_info); void OnZoomLevelChanged(double zoom_level); + void OnRootWindowSegmentsChanged( + std::vector<gfx::Rect> root_widget_window_segments); void OnPageScaleFactorChanged(float page_scale_factor, bool is_pinch_gesture_active); void OnVisibleViewportSizeChanged(const gfx::Size& visible_viewport_size); @@ -177,10 +179,8 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, // blink::WebRemoteFrameClient implementation: void FrameDetached(DetachType type) override; - void ForwardPostMessage(blink::WebLocalFrame* sourceFrame, - blink::WebRemoteFrame* targetFrame, - blink::WebSecurityOrigin target, - blink::WebDOMMessageEvent event) override; + blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override; + void Navigate( const blink::WebURLRequest& request, blink::WebLocalFrame* initiator_frame, @@ -189,15 +189,13 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, bool initiator_frame_has_download_sandbox_flag, bool blocking_downloads_in_sandbox_enabled, bool initiator_frame_is_ad, - mojo::ScopedMessagePipeHandle blob_url_token, + blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase> + blob_url_token, const base::Optional<blink::WebImpression>& impression) override; void FrameRectsChanged(const blink::WebRect& local_frame_rect, const blink::WebRect& screen_space_rect) override; void UpdateRemoteViewportIntersection( const blink::ViewportIntersectionState& intersection_state) override; - void DidChangeOpener(blink::WebFrame* opener) override; - void AdvanceFocus(blink::mojom::FocusType type, - blink::WebLocalFrame* source) override; base::UnguessableToken GetDevToolsFrameToken() override; uint32_t Print(const blink::WebRect& rect, cc::PaintCanvas* canvas) override; @@ -223,16 +221,13 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, void ResendVisualProperties(); mojom::RenderFrameProxyHost* GetFrameProxyHost(); - blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces(); // IPC handlers void OnDeleteProxy(); void OnCompositorFrameSwapped(const IPC::Message& message); - void OnUpdateOpener(int opener_routing_id); void OnDidUpdateName(const std::string& name, const std::string& unique_name); void OnEnforceInsecureRequestPolicy( blink::mojom::InsecureRequestPolicy policy); - void OnTransferUserActivationFrom(int32_t source_routing_id); // mojom::RenderFrameProxy implementation: void EnableAutoResize(const gfx::Size& min_size, diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc index b305148481d..baee6cbd636 100644 --- a/chromium/content/renderer/render_thread_impl.cc +++ b/chromium/content/renderer/render_thread_impl.cc @@ -80,7 +80,6 @@ #include "content/renderer/frame_swap_message_queue.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/loader/resource_dispatcher.h" -#include "content/renderer/low_memory_mode_controller.h" #include "content/renderer/media/audio/audio_renderer_mixer_manager.h" #include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h" #include "content/renderer/media/render_media_client.h" @@ -126,6 +125,7 @@ #include "services/viz/public/cpp/gpu/gpu.h" #include "skia/ext/skia_memory_dump_provider.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/switches.h" #include "third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/web_cache.h" @@ -151,7 +151,7 @@ #if defined(OS_ANDROID) #include <cpu-features.h> -#include "content/renderer/android/synchronous_layer_tree_frame_sink.h" +#include "content/renderer/android/synchronous_layer_tree_frame_sink_impl.h" #include "content/renderer/media/android/stream_texture_factory.h" #include "media/base/android/media_codec_util.h" #endif @@ -655,11 +655,12 @@ void RenderThreadImpl::Init() { is_threaded_animation_enabled_ = !command_line.HasSwitch(cc::switches::kDisableThreadedAnimation); - is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy); + is_zero_copy_enabled_ = + command_line.HasSwitch(blink::switches::kEnableZeroCopy); is_partial_raster_enabled_ = - !command_line.HasSwitch(switches::kDisablePartialRaster); + !command_line.HasSwitch(blink::switches::kDisablePartialRaster); is_gpu_memory_buffer_compositor_resources_enabled_ = command_line.HasSwitch( - switches::kEnableGpuMemoryBufferCompositorResources); + blink::switches::kEnableGpuMemoryBufferCompositorResources); // On macOS this value is adjusted in `UpdateScrollbarTheme()`, // but the system default is true. @@ -681,6 +682,11 @@ void RenderThreadImpl::Init() { } else { #if defined(OS_ANDROID) is_lcd_text_enabled_ = false; +#elif defined(OS_MACOSX) + if (base::FeatureList::IsEnabled(features::kRespectMacLCDTextSetting)) + is_lcd_text_enabled_ = IsSubpixelAntialiasingAvailable(); + else + is_lcd_text_enabled_ = true; #else is_lcd_text_enabled_ = true; #endif @@ -689,9 +695,10 @@ void RenderThreadImpl::Init() { if (command_line.HasSwitch(switches::kDisableGpuCompositing)) is_gpu_compositing_disabled_ = true; - if (command_line.HasSwitch(switches::kGpuRasterizationMSAASampleCount)) { + if (command_line.HasSwitch( + blink::switches::kGpuRasterizationMSAASampleCount)) { std::string string_value = command_line.GetSwitchValueASCII( - switches::kGpuRasterizationMSAASampleCount); + blink::switches::kGpuRasterizationMSAASampleCount); bool parsed_msaa_sample_count = base::StringToInt(string_value, &gpu_rasterization_msaa_sample_count_); DCHECK(parsed_msaa_sample_count) << string_value; @@ -731,6 +738,7 @@ void RenderThreadImpl::Init() { #endif memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( + FROM_HERE, base::BindRepeating(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this)), base::BindRepeating(&RenderThreadImpl::OnSyncMemoryPressure, @@ -1055,6 +1063,8 @@ void RenderThreadImpl::RegisterSchemes() { WebString::FromASCII(kChromeUIUntrustedScheme)); WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs( chrome_untrusted_scheme); + WebSecurityPolicy::RegisterURLSchemeAsSupportingFetchAPI( + chrome_untrusted_scheme); // devtools: WebString devtools_scheme(WebString::FromASCII(kChromeDevToolsScheme)); @@ -1240,7 +1250,7 @@ RenderThreadImpl::SharedMainThreadContextProvider() { bool support_raster_interface = true; bool support_oop_rasterization = base::FeatureList::IsEnabled(features::kCanvasOopRasterization); - bool support_gles2_interface = !support_oop_rasterization; + bool support_gles2_interface = false; bool support_grcontext = !support_oop_rasterization; // Enable automatic flushes to improve canvas throughput. // See https://crbug.com/880901 @@ -1482,11 +1492,6 @@ void RenderThreadImpl::SetIsLockedToSite() { blink_platform_impl_->SetIsLockedToSite(); } -void RenderThreadImpl::EnableV8LowMemoryMode() { - if (!low_memory_mode_controller_) - low_memory_mode_controller_.reset(new LowMemoryModeController()); -} - #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) void RenderThreadImpl::WriteClangProfilingProfile( WriteClangProfilingProfileCallback callback) { @@ -1497,6 +1502,10 @@ void RenderThreadImpl::WriteClangProfilingProfile( } #endif +void RenderThreadImpl::SetIsCrossOriginIsolated(bool value) { + blink::SetIsCrossOriginIsolated(value); +} + bool RenderThreadImpl::GetRendererMemoryMetrics( RendererMemoryMetrics* memory_metrics) const { DCHECK(memory_metrics); @@ -1826,11 +1835,10 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( std::move(render_frame_metadata_observer_remote)); std::move(callback).Run( - std::make_unique<SynchronousLayerTreeFrameSink>( + std::make_unique<SynchronousLayerTreeFrameSinkImpl>( std::move(context_provider), std::move(worker_context_provider), compositor_task_runner_, GetGpuMemoryBufferManager(), - sync_message_filter(), render_widget->routing_id(), - g_next_layer_tree_frame_sink_id++, + sync_message_filter(), g_next_layer_tree_frame_sink_id++, std::move(params.synthetic_begin_frame_source), render_widget->widget_input_handler_manager() ->GetSynchronousCompositorRegistry(), @@ -1905,9 +1913,10 @@ void RenderThreadImpl::CreateFrame(mojom::CreateFrameParamsPtr params) { RenderFrameImpl::CreateFrame( params->routing_id, std::move(interface_provider), std::move(browser_interface_broker), params->previous_routing_id, - params->opener_routing_id, params->parent_routing_id, - params->previous_sibling_routing_id, params->frame_token, - params->devtools_frame_token, params->replication_state, compositor_deps, + params->opener_frame_token.value_or(base::UnguessableToken()), + params->parent_routing_id, params->previous_sibling_routing_id, + params->frame_token, params->devtools_frame_token, + params->replication_state, compositor_deps, std::move(params->widget_params), std::move(params->frame_owner_properties), params->has_committed_real_load); @@ -1916,14 +1925,14 @@ void RenderThreadImpl::CreateFrame(mojom::CreateFrameParamsPtr params) { void RenderThreadImpl::CreateFrameProxy( int32_t routing_id, int32_t render_view_routing_id, - int32_t opener_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, int32_t parent_routing_id, const FrameReplicationState& replicated_state, const base::UnguessableToken& frame_token, const base::UnguessableToken& devtools_frame_token) { RenderFrameProxy::CreateFrameProxy( routing_id, render_view_routing_id, - RenderFrameImpl::ResolveWebFrame(opener_routing_id), parent_routing_id, + opener_frame_token.value_or(base::UnguessableToken()), parent_routing_id, replicated_state, frame_token, devtools_frame_token); } @@ -1974,6 +1983,11 @@ void RenderThreadImpl::SetUserAgentMetadata( user_agent_metadata_ = user_agent_metadata; } +void RenderThreadImpl::SetCorsExemptHeaderList( + const std::vector<std::string>& list) { + resource_dispatcher_->SetCorsExemptHeaderList(list); +} + void RenderThreadImpl::UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) { #if defined(OS_MACOSX) @@ -2041,18 +2055,6 @@ void RenderThreadImpl::OnMemoryPressure( } } -void RenderThreadImpl::RecordPurgeMemory(RendererMemoryMetrics before) { - RendererMemoryMetrics after; - if (!GetRendererMemoryMetrics(&after)) - return; - int64_t mbytes = static_cast<int64_t>(before.total_allocated_mb) - - static_cast<int64_t>(after.total_allocated_mb); - if (mbytes < 0) - mbytes = 0; - UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Renderer.PurgedMemory", - mbytes); -} - scoped_refptr<base::SingleThreadTaskRunner> RenderThreadImpl::GetMediaThreadTaskRunner() { DCHECK(main_thread_runner()->BelongsToCurrentThread()); diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h index 301ea6a3055..d94334980bb 100644 --- a/chromium/content/renderer/render_thread_impl.h +++ b/chromium/content/renderer/render_thread_impl.h @@ -103,7 +103,6 @@ namespace content { class AudioRendererMixerManager; class CategorizedWorkerPool; class GpuVideoAcceleratorFactoriesImpl; -class LowMemoryModeController; class RenderThreadObserver; class RendererBlinkPlatformImpl; class ResourceDispatcher; @@ -271,10 +270,6 @@ class CONTENT_EXPORT RenderThreadImpl return vc_manager_.get(); } - LowMemoryModeController* low_memory_mode_controller() const { - return low_memory_mode_controller_.get(); - } - mojom::RenderMessageFilter* render_message_filter(); // Get the GPU channel. Returns NULL if the channel is not established or @@ -445,8 +440,6 @@ class CONTENT_EXPORT RenderThreadImpl bool IsMainThread(); - void RecordPurgeMemory(RendererMemoryMetrics before); - void Init(); void InitializeCompositorThread(); void InitializeWebKit(mojo::BinderMap* binders); @@ -461,7 +454,7 @@ class CONTENT_EXPORT RenderThreadImpl void CreateFrameProxy( int32_t routing_id, int32_t render_view_routing_id, - int32_t opener_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, int32_t parent_routing_id, const FrameReplicationState& replicated_state, const base::UnguessableToken& frame_token, @@ -476,6 +469,7 @@ class CONTENT_EXPORT RenderThreadImpl void SetWebKitSharedTimersSuspended(bool suspend) override; void SetUserAgent(const std::string& user_agent) override; void SetUserAgentMetadata(const blink::UserAgentMetadata& metadata) override; + void SetCorsExemptHeaderList(const std::vector<std::string>& list) override; void UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) override; void OnSystemColorsChanged(int32_t aqua_color_variant, @@ -488,11 +482,11 @@ class CONTENT_EXPORT RenderThreadImpl mojom::RenderProcessVisibleState visible_state) override; void SetSchedulerKeepActive(bool keep_active) override; void SetIsLockedToSite() override; - void EnableV8LowMemoryMode() override; #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) void WriteClangProfilingProfile( WriteClangProfilingProfileCallback callback) override; #endif + void SetIsCrossOriginIsolated(bool value) override; void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); @@ -596,10 +590,6 @@ class CONTENT_EXPORT RenderThreadImpl std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - // Created in response to EnableV8LowMemoryMode(), this manages V8's - // memory saving mode. - std::unique_ptr<LowMemoryModeController> low_memory_mode_controller_; - std::unique_ptr<viz::Gpu> gpu_; std::unique_ptr<VariationsRenderThreadObserver> variations_observer_; diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc index 9add01eef49..9adedadf716 100644 --- a/chromium/content/renderer/render_thread_impl_browsertest.cc +++ b/chromium/content/renderer/render_thread_impl_browsertest.cc @@ -21,7 +21,6 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" -#include "base/task/post_task.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/test_switches.h" #include "base/threading/sequenced_task_runner_handle.h" @@ -157,7 +156,7 @@ class RenderThreadImplBrowserTest : public testing::Test, browser_threads_.reset( new BrowserTaskEnvironment(BrowserTaskEnvironment::REAL_IO_THREAD)); scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = - base::CreateSingleThreadTaskRunner({BrowserThread::IO}); + GetIOThreadTaskRunner({}); InitializeMojo(); process_host_ = diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc index d6f4b3560ae..17a6f4e8da8 100644 --- a/chromium/content/renderer/render_view_browsertest.cc +++ b/chromium/content/renderer/render_view_browsertest.cc @@ -18,7 +18,6 @@ #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "base/test/bind_test_util.h" #include "base/test/gmock_callback_support.h" #include "base/threading/thread_task_runner_handle.h" @@ -43,6 +42,7 @@ #include "content/public/common/use_zoom_for_dsf_policy.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/test/browser_test_utils.h" +#include "content/public/test/fake_render_widget_host.h" #include "content/public/test/frame_load_waiter.h" #include "content/public/test/local_frame_host_interceptor.h" #include "content/public/test/render_view_test.h" @@ -63,6 +63,7 @@ #include "content/test/mock_keyboard.h" #include "content/test/test_render_frame.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/mojom/base/text_direction.mojom-blink.h" #include "net/base/net_errors.h" #include "net/cert/cert_status_flags.h" #include "net/dns/public/resolve_error_info.h" @@ -99,6 +100,7 @@ #include "third_party/blink/public/web/web_view.h" #include "third_party/blink/public/web/web_window_features.h" #include "ui/accessibility/ax_mode.h" +#include "ui/base/ime/mojom/text_input_state.mojom.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -132,6 +134,10 @@ #include "ui/events/keycodes/keyboard_code_conversion.h" #endif +#if defined(USE_X11) && defined(USE_OZONE) +#include "ui/base/ui_base_features.h" +#endif + using base::TimeDelta; using blink::WebFrame; using blink::WebFrameContentDumper; @@ -256,6 +262,14 @@ class RenderViewImplTest : public RenderViewTest { return static_cast<TestRenderFrame*>(view()->GetMainRenderFrame()); } + blink::mojom::FrameWidgetInputHandler* GetFrameWidgetInputHandler() { + return render_widget_host_->GetFrameWidgetInputHandler(); + } + + blink::mojom::WidgetInputHandler* GetWidgetInputHandler() { + return render_widget_host_->GetWidgetInputHandler(); + } + RenderAccessibilityManager* GetRenderAccessibilityManager() { return frame()->GetRenderAccessibilityManager(); } @@ -264,6 +278,13 @@ class RenderViewImplTest : public RenderViewTest { return GetRenderAccessibilityManager()->GetAccessibilityMode(); } + const std::vector<gfx::Rect>& LastCompositionBounds() { + render_widget_host_->GetWidgetInputHandler()->RequestCompositionUpdates( + true, false); + base::RunLoop().RunUntilIdle(); + return render_widget_host_->LastCompositionBounds(); + } + void ReceiveDisableDeviceEmulation(RenderViewImpl* view) { // Emulates receiving an IPC message. RenderWidget* widget = @@ -280,12 +301,6 @@ class RenderViewImplTest : public RenderViewTest { widget->OnEnableDeviceEmulation(params); } - void ReceiveSetTextDirection(RenderWidget* widget, - base::i18n::TextDirection direction) { - // Emulates receiving an IPC message. - widget->OnSetTextDirection(direction); - } - void GoToOffsetWithParams(int offset, const PageState& state, mojom::CommonNavigationParamsPtr common_params, @@ -317,47 +332,11 @@ class RenderViewImplTest : public RenderViewTest { return param; } - // Sends IPC messages that emulates a key-press event. - int SendKeyEvent(MockKeyboard::Layout layout, - int key_code, - MockKeyboard::Modifiers modifiers, - base::string16* output) { -#if defined(OS_WIN) - // Retrieve the Unicode character for the given tuple (keyboard-layout, - // key-code, and modifiers). - // Exit when a keyboard-layout driver cannot assign a Unicode character to - // the tuple to prevent sending an invalid key code to the RenderView - // object. - CHECK(mock_keyboard_.get()); - CHECK(output); - int length = mock_keyboard_->GetCharacters(layout, key_code, modifiers, - output); - if (length != 1) - return -1; - - // Create IPC messages from Windows messages and send them to our - // back-end. - // A keyboard event of Windows consists of three Windows messages: - // WM_KEYDOWN, WM_CHAR, and WM_KEYUP. - // WM_KEYDOWN and WM_KEYUP sends virtual-key codes. On the other hand, - // WM_CHAR sends a composed Unicode character. - MSG msg1 = { NULL, WM_KEYDOWN, key_code, 0 }; - ui::KeyEvent evt1(msg1); - NativeWebKeyboardEvent keydown_event(evt1); - SendNativeKeyEvent(keydown_event); - - MSG msg2 = { NULL, WM_CHAR, (*output)[0], 0 }; - ui::KeyEvent evt2(msg2); - NativeWebKeyboardEvent char_event(evt2); - SendNativeKeyEvent(char_event); - - MSG msg3 = { NULL, WM_KEYUP, key_code, 0 }; - ui::KeyEvent evt3(msg3); - NativeWebKeyboardEvent keyup_event(evt3); - SendNativeKeyEvent(keyup_event); - - return length; -#elif defined(USE_AURA) && defined(USE_X11) +#if defined(USE_X11) + int SendKeyEventX11(MockKeyboard::Layout layout, + int key_code, + MockKeyboard::Modifiers modifiers, + base::string16* output) { // We ignore |layout|, which means we are only testing the layout of the // current locale. TODO(mazda): fix this to respect |layout|. CHECK(output); @@ -365,8 +344,7 @@ class RenderViewImplTest : public RenderViewTest { ui::ScopedXI2Event xevent; xevent.InitKeyEvent(ui::ET_KEY_PRESSED, - static_cast<ui::KeyboardCode>(key_code), - flags); + static_cast<ui::KeyboardCode>(key_code), flags); auto event1 = ui::BuildKeyEventFromXEvent(*xevent); NativeWebKeyboardEvent keydown_event(*event1); SendNativeKeyEvent(keydown_event); @@ -374,8 +352,7 @@ class RenderViewImplTest : public RenderViewTest { // X11 doesn't actually have native character events, but give the test // what it wants. xevent.InitKeyEvent(ui::ET_KEY_PRESSED, - static_cast<ui::KeyboardCode>(key_code), - flags); + static_cast<ui::KeyboardCode>(key_code), flags); auto event2 = ui::BuildKeyEventFromXEvent(*xevent); event2->set_character( DomCodeToUsLayoutCharacter(event2->code(), event2->flags())); @@ -385,8 +362,7 @@ class RenderViewImplTest : public RenderViewTest { SendNativeKeyEvent(char_event); xevent.InitKeyEvent(ui::ET_KEY_RELEASED, - static_cast<ui::KeyboardCode>(key_code), - flags); + static_cast<ui::KeyboardCode>(key_code), flags); auto event3 = ui::BuildKeyEventFromXEvent(*xevent); NativeWebKeyboardEvent keyup_event(*event3); SendNativeKeyEvent(keyup_event); @@ -396,12 +372,18 @@ class RenderViewImplTest : public RenderViewTest { flags); output->assign(1, static_cast<base::char16>(c)); return 1; -#elif defined(USE_OZONE) - const int flags = ConvertMockKeyboardModifier(modifiers); + } +#endif + +#if defined(USE_OZONE) + int SendKeyEventOzone(MockKeyboard::Layout layout, + int key_code, + MockKeyboard::Modifiers modifiers, + base::string16* output) { + int flags = ConvertMockKeyboardModifier(modifiers); ui::KeyEvent keydown_event(ui::ET_KEY_PRESSED, - static_cast<ui::KeyboardCode>(key_code), - flags); + static_cast<ui::KeyboardCode>(key_code), flags); NativeWebKeyboardEvent keydown_web_event(keydown_event); SendNativeKeyEvent(keydown_web_event); @@ -412,8 +394,7 @@ class RenderViewImplTest : public RenderViewTest { SendNativeKeyEvent(char_web_event); ui::KeyEvent keyup_event(ui::ET_KEY_RELEASED, - static_cast<ui::KeyboardCode>(key_code), - flags); + static_cast<ui::KeyboardCode>(key_code), flags); NativeWebKeyboardEvent keyup_web_event(keyup_event); SendNativeKeyEvent(keyup_web_event); @@ -422,6 +403,57 @@ class RenderViewImplTest : public RenderViewTest { flags); output->assign(1, static_cast<base::char16>(c)); return 1; + } +#endif + + // Sends IPC messages that emulates a key-press event. + int SendKeyEvent(MockKeyboard::Layout layout, + int key_code, + MockKeyboard::Modifiers modifiers, + base::string16* output) { +#if defined(OS_WIN) + // Retrieve the Unicode character for the given tuple (keyboard-layout, + // key-code, and modifiers). + // Exit when a keyboard-layout driver cannot assign a Unicode character to + // the tuple to prevent sending an invalid key code to the RenderView + // object. + CHECK(mock_keyboard_.get()); + CHECK(output); + int length = + mock_keyboard_->GetCharacters(layout, key_code, modifiers, output); + if (length != 1) + return -1; + + // Create IPC messages from Windows messages and send them to our + // back-end. + // A keyboard event of Windows consists of three Windows messages: + // WM_KEYDOWN, WM_CHAR, and WM_KEYUP. + // WM_KEYDOWN and WM_KEYUP sends virtual-key codes. On the other hand, + // WM_CHAR sends a composed Unicode character. + MSG msg1 = {NULL, WM_KEYDOWN, key_code, 0}; + ui::KeyEvent evt1(msg1); + NativeWebKeyboardEvent keydown_event(evt1); + SendNativeKeyEvent(keydown_event); + + MSG msg2 = {NULL, WM_CHAR, (*output)[0], 0}; + ui::KeyEvent evt2(msg2); + NativeWebKeyboardEvent char_event(evt2); + SendNativeKeyEvent(char_event); + + MSG msg3 = {NULL, WM_KEYUP, key_code, 0}; + ui::KeyEvent evt3(msg3); + NativeWebKeyboardEvent keyup_event(evt3); + SendNativeKeyEvent(keyup_event); + + return length; +#elif defined(USE_X11) +#if defined(USE_OZONE) + if (features::IsUsingOzonePlatform()) + return SendKeyEventOzone(layout, key_code, modifiers, output); +#endif + return SendKeyEventX11(layout, key_code, modifiers, output); +#elif defined(USE_OZONE) + return SendKeyEventOzone(layout, key_code, modifiers, output); #else NOTIMPLEMENTED(); return L'\0'; @@ -624,9 +656,7 @@ TEST_F(RenderViewImplTest, OnNavStateChanged) { LoadHTML("<input type=\"text\" id=\"elt_text\"></input>"); // We should NOT have gotten a form state change notification yet. - EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( - FrameHostMsg_UpdateState::ID)); - render_thread_->sink().ClearMessages(); + EXPECT_FALSE(frame()->IsPageStateUpdated()); // Change the value of the input. We should have gotten an update state // notification. We need to spin the message loop to catch this update. @@ -634,8 +664,8 @@ TEST_F(RenderViewImplTest, OnNavStateChanged) { "document.getElementById('elt_text').value = 'foo';"); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_UpdateState::ID)); + // Check the page state is updated after the value of the input is changed. + EXPECT_TRUE(frame()->IsPageStateUpdated()); } class RenderViewImplEmulatingPopupTest : public RenderViewImplTest { @@ -941,8 +971,7 @@ TEST_F(RenderViewImplTest, BeginNavigation) { blink::kWebNavigationPolicyCurrentTab; render_thread_->sink().ClearMessages(); frame()->BeginNavigation(std::move(form_navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); // Popup links to WebUI URLs. blink::WebURLRequest popup_request(GetWebUIURL("foo")); @@ -962,8 +991,7 @@ TEST_F(RenderViewImplTest, BeginNavigation) { blink::kWebNavigationPolicyNewForegroundTab; render_thread_->sink().ClearMessages(); frame()->BeginNavigation(std::move(popup_navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); } TEST_F(RenderViewImplTest, BeginNavigationHandlesAllTopLevel) { @@ -992,8 +1020,7 @@ TEST_F(RenderViewImplTest, BeginNavigationHandlesAllTopLevel) { render_thread_->sink().ClearMessages(); frame()->BeginNavigation(std::move(navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); } } @@ -1020,8 +1047,7 @@ TEST_F(RenderViewImplTest, BeginNavigationForWebUI) { render_thread_->sink().ClearMessages(); frame()->BeginNavigation(std::move(navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); // Navigations to WebUI URLs. auto webui_navigation_info = std::make_unique<blink::WebNavigationInfo>(); @@ -1040,8 +1066,7 @@ TEST_F(RenderViewImplTest, BeginNavigationForWebUI) { blink::kWebNavigationPolicyCurrentTab; render_thread_->sink().ClearMessages(); frame()->BeginNavigation(std::move(webui_navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); // Form posts to data URLs. auto data_navigation_info = std::make_unique<blink::WebNavigationInfo>(); @@ -1067,8 +1092,7 @@ TEST_F(RenderViewImplTest, BeginNavigationForWebUI) { blink::kWebNavigationPolicyCurrentTab; render_thread_->sink().ClearMessages(); frame()->BeginNavigation(std::move(data_navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); // A popup that creates a view first and then navigates to a // normal HTTP URL. @@ -1094,8 +1118,7 @@ TEST_F(RenderViewImplTest, BeginNavigationForWebUI) { render_thread_->sink().ClearMessages(); static_cast<RenderFrameImpl*>(new_view->GetMainRenderFrame()) ->BeginNavigation(std::move(popup_navigation_info)); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_OpenURL::ID)); + EXPECT_TRUE(frame()->IsURLOpened()); } // This test verifies that when device emulation is enabled, RenderFrameProxy @@ -1248,7 +1271,7 @@ TEST_F(RenderViewImplEnableZoomForDSFTest, RenderFrameImpl::CreateFrame( routing_id, std::move(stub_interface_provider), std::move(stub_browser_interface_broker), kProxyRoutingId, - MSG_ROUTING_NONE, MSG_ROUTING_NONE, MSG_ROUTING_NONE, + base::UnguessableToken(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(), base::UnguessableToken::Create(), replication_state, compositor_deps_.get(), std::move(widget_params), blink::mojom::FrameOwnerProperties::New(), @@ -1316,7 +1339,7 @@ TEST_F(RenderViewImplTest, DetachingProxyAlsoDestroysProvisionalFrame) { RenderFrameImpl::CreateFrame( routing_id, std::move(stub_interface_provider), std::move(stub_browser_interface_broker), kProxyRoutingId, - MSG_ROUTING_NONE, frame()->GetRoutingID(), MSG_ROUTING_NONE, + base::UnguessableToken(), frame()->GetRoutingID(), MSG_ROUTING_NONE, base::UnguessableToken::Create(), base::UnguessableToken::Create(), replication_state, nullptr, /*widget_params=*/nullptr, blink::mojom::FrameOwnerProperties::New(), @@ -1360,9 +1383,43 @@ TEST_F(RenderViewImplEnableZoomForDSFTest, EXPECT_TRUE(view()->GetWebView()->MainFrame()->IsWebRemoteFrame()); } +class TextInputStateFakeRenderWidgetHost : public FakeRenderWidgetHost { + public: + void TextInputStateChanged(ui::mojom::TextInputStatePtr state) override { + updated_states_.push_back(std::move(state)); + } + + const std::vector<ui::mojom::TextInputStatePtr>& updated_states() { + return updated_states_; + } + + void ClearState() { updated_states_.clear(); } + + private: + std::vector<ui::mojom::TextInputStatePtr> updated_states_; +}; + +class RenderViewImplTextInputStateChanged : public RenderViewImplTest { + public: + std::unique_ptr<FakeRenderWidgetHost> CreateRenderWidgetHost() override { + return std::make_unique<TextInputStateFakeRenderWidgetHost>(); + } + + const std::vector<ui::mojom::TextInputStatePtr>& updated_states() { + return static_cast<TextInputStateFakeRenderWidgetHost*>( + render_widget_host_.get()) + ->updated_states(); + } + + void ClearState() { + static_cast<TextInputStateFakeRenderWidgetHost*>(render_widget_host_.get()) + ->ClearState(); + } +}; + // Test that our IME backend sends a notification message when the input focus // changes. -TEST_F(RenderViewImplTest, OnImeTypeChanged) { +TEST_F(RenderViewImplTextInputStateChanged, OnImeTypeChanged) { // Load an HTML page consisting of two input fields. LoadHTML( "<html>" @@ -1382,7 +1439,6 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) { "<input id=\"test11\" type=\"text\" inputmode=\"unknown\"></input>" "</body>" "</html>"); - render_thread_->sink().ClearMessages(); struct InputModeTestCase { const char* input_id; @@ -1407,21 +1463,16 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) { // activate IMEs. ExecuteJavaScriptForTests("document.getElementById('test1').focus();"); base::RunLoop().RunUntilIdle(); - render_thread_->sink().ClearMessages(); + ClearState(); // Update the IME status and verify if our IME backend sends an IPC message // to activate IMEs. main_widget()->UpdateTextInputState(); - const IPC::Message* msg = render_thread_->sink().GetMessageAt(0); - EXPECT_TRUE(msg != nullptr); - EXPECT_EQ(static_cast<uint32_t>(WidgetHostMsg_TextInputStateChanged::ID), - msg->type()); - WidgetHostMsg_TextInputStateChanged::Param params; - WidgetHostMsg_TextInputStateChanged::Read(msg, ¶ms); - TextInputState p = std::get<0>(params); - ui::TextInputType type = p.type; - ui::TextInputMode input_mode = p.mode; - bool can_compose_inline = p.can_compose_inline; + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + ui::TextInputType type = updated_states()[0]->type; + ui::TextInputMode input_mode = updated_states()[0]->mode; + bool can_compose_inline = updated_states()[0]->can_compose_inline; EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, type); EXPECT_EQ(true, can_compose_inline); @@ -1429,19 +1480,15 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) { // de-activate IMEs. ExecuteJavaScriptForTests("document.getElementById('test2').focus();"); base::RunLoop().RunUntilIdle(); - render_thread_->sink().ClearMessages(); + ClearState(); // Update the IME status and verify if our IME backend sends an IPC message // to de-activate IMEs. main_widget()->UpdateTextInputState(); - msg = render_thread_->sink().GetMessageAt(0); - EXPECT_TRUE(msg != nullptr); - EXPECT_EQ(static_cast<uint32_t>(WidgetHostMsg_TextInputStateChanged::ID), - msg->type()); - WidgetHostMsg_TextInputStateChanged::Read(msg, ¶ms); - p = std::get<0>(params); - type = p.type; - input_mode = p.mode; + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + type = updated_states()[0]->type; + input_mode = updated_states()[0]->mode; EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, type); for (size_t i = 0; i < base::size(kInputModeTestCases); i++) { @@ -1454,26 +1501,22 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) { ExecuteJavaScriptAndReturnIntValue(base::ASCIIToUTF16(javascript), nullptr); base::RunLoop().RunUntilIdle(); - render_thread_->sink().ClearMessages(); + ClearState(); // Update the IME status and verify if our IME backend sends an IPC // message to activate IMEs. main_widget()->UpdateTextInputState(); base::RunLoop().RunUntilIdle(); - const IPC::Message* msg = render_thread_->sink().GetMessageAt(0); - EXPECT_TRUE(msg != nullptr); - EXPECT_EQ(static_cast<uint32_t>(WidgetHostMsg_TextInputStateChanged::ID), - msg->type()); - WidgetHostMsg_TextInputStateChanged::Read(msg, ¶ms); - p = std::get<0>(params); - type = p.type; - input_mode = p.mode; + EXPECT_EQ(1u, updated_states().size()); + type = updated_states()[0]->type; + input_mode = updated_states()[0]->mode; EXPECT_EQ(test_case->expected_mode, input_mode); } } } -TEST_F(RenderViewImplTest, ShouldSuppressKeyboardIsPropagated) { +TEST_F(RenderViewImplTextInputStateChanged, + ShouldSuppressKeyboardIsPropagated) { class TestAutofillClient : public blink::WebAutofillClient { public: TestAutofillClient() = default; @@ -1508,25 +1551,27 @@ TEST_F(RenderViewImplTest, ShouldSuppressKeyboardIsPropagated) { // Focus the text field, trigger a state update and check that the right IPC // is sent. ExecuteJavaScriptForTests("document.getElementById('test').focus();"); - base::RunLoop().RunUntilIdle(); main_widget()->UpdateTextInputState(); - auto params = ProcessAndReadIPC<WidgetHostMsg_TextInputStateChanged>(); - EXPECT_FALSE(std::get<0>(params).always_hide_ime); - render_thread_->sink().ClearMessages(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_FALSE(updated_states()[0]->always_hide_ime); + ClearState(); // Tell the client to suppress the keyboard. Check whether always_hide_ime is // set correctly. client.SetShouldSuppressKeyboard(true); main_widget()->UpdateTextInputState(); - params = ProcessAndReadIPC<WidgetHostMsg_TextInputStateChanged>(); - EXPECT_TRUE(std::get<0>(params).always_hide_ime); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_TRUE(updated_states()[0]->always_hide_ime); // Explicitly clean-up the autofill client, as otherwise a use-after-free // happens. GetMainFrame()->SetAutofillClient(nullptr); } -TEST_F(RenderViewImplTest, EditContextGetLayoutBoundsAndInputPanelPolicy) { +TEST_F(RenderViewImplTextInputStateChanged, + EditContextGetLayoutBoundsAndInputPanelPolicy) { // Load an HTML page. LoadHTML( "<html>" @@ -1535,7 +1580,7 @@ TEST_F(RenderViewImplTest, EditContextGetLayoutBoundsAndInputPanelPolicy) { "<body>" "</body>" "</html>"); - render_thread_->sink().ClearMessages(); + ClearState(); // Create an EditContext with control and selection bounds and set input // panel policy to auto. ExecuteJavaScriptForTests( @@ -1547,30 +1592,32 @@ TEST_F(RenderViewImplTest, EditContextGetLayoutBoundsAndInputPanelPolicy) { // This RunLoop is waiting for EditContext to be created and layout bounds // to be updated in the EditContext. base::RunLoop run_loop; - base::PostTask(FROM_HERE, run_loop.QuitClosure()); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); run_loop.Run(); // Update the IME status and verify if our IME backend sends an IPC message // to notify layout bounds of the EditContext. main_widget()->UpdateTextInputState(); - auto params = ProcessAndReadIPC<WidgetHostMsg_TextInputStateChanged>(); - EXPECT_EQ(true, std::get<0>(params).show_ime_if_needed); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); blink::WebRect edit_context_control_bounds_expected(10, 20, 30, 40); blink::WebRect edit_context_selection_bounds_expected(10, 20, 1, 5); main_widget()->ConvertViewportToWindow(&edit_context_control_bounds_expected); main_widget()->ConvertViewportToWindow( &edit_context_selection_bounds_expected); blink::WebRect actual_active_element_control_bounds( - std::get<0>(params).edit_context_control_bounds.value()); + updated_states()[0]->edit_context_control_bounds.value()); blink::WebRect actual_active_element_selection_bounds( - std::get<0>(params).edit_context_selection_bounds.value()); + updated_states()[0]->edit_context_selection_bounds.value()); EXPECT_EQ(edit_context_control_bounds_expected, actual_active_element_control_bounds); EXPECT_EQ(edit_context_selection_bounds_expected, actual_active_element_selection_bounds); } -TEST_F(RenderViewImplTest, EditContextGetLayoutBoundsWithFloatingValues) { +TEST_F(RenderViewImplTextInputStateChanged, + EditContextGetLayoutBoundsWithFloatingValues) { // Load an HTML page. LoadHTML( "<html>" @@ -1579,7 +1626,7 @@ TEST_F(RenderViewImplTest, EditContextGetLayoutBoundsWithFloatingValues) { "<body>" "</body>" "</html>"); - render_thread_->sink().ClearMessages(); + ClearState(); // Create an EditContext with control and selection bounds and set input // panel policy to auto. ExecuteJavaScriptForTests( @@ -1591,29 +1638,30 @@ TEST_F(RenderViewImplTest, EditContextGetLayoutBoundsWithFloatingValues) { // This RunLoop is waiting for EditContext to be created and layout bounds // to be updated in the EditContext. base::RunLoop run_loop; - base::PostTask(FROM_HERE, run_loop.QuitClosure()); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); run_loop.Run(); // Update the IME status and verify if our IME backend sends an IPC message // to notify layout bounds of the EditContext. main_widget()->UpdateTextInputState(); - auto params = ProcessAndReadIPC<WidgetHostMsg_TextInputStateChanged>(); - EXPECT_EQ(true, std::get<0>(params).show_ime_if_needed); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); blink::WebRect edit_context_control_bounds_expected(10, 20, 31, 41); blink::WebRect edit_context_selection_bounds_expected(10, 20, 1, 5); main_widget()->ConvertViewportToWindow(&edit_context_control_bounds_expected); main_widget()->ConvertViewportToWindow( &edit_context_selection_bounds_expected); blink::WebRect actual_active_element_control_bounds( - std::get<0>(params).edit_context_control_bounds.value()); + updated_states()[0]->edit_context_control_bounds.value()); blink::WebRect actual_active_element_selection_bounds( - std::get<0>(params).edit_context_selection_bounds.value()); + updated_states()[0]->edit_context_selection_bounds.value()); EXPECT_EQ(edit_context_control_bounds_expected, actual_active_element_control_bounds); EXPECT_EQ(edit_context_selection_bounds_expected, actual_active_element_selection_bounds); } -TEST_F(RenderViewImplTest, ActiveElementGetLayoutBounds) { +TEST_F(RenderViewImplTextInputStateChanged, ActiveElementGetLayoutBounds) { // Load an HTML page consisting of one input fields. LoadHTML( "<html>" @@ -1623,18 +1671,20 @@ TEST_F(RenderViewImplTest, ActiveElementGetLayoutBounds) { "<input id=\"test\" type=\"text\"></input>" "</body>" "</html>"); - render_thread_->sink().ClearMessages(); + ClearState(); // Create an EditContext with control and selection bounds and set input // panel policy to auto. ExecuteJavaScriptForTests("document.getElementById('test').focus();"); // This RunLoop is waiting for focus to be processed for the active element. base::RunLoop run_loop; - base::PostTask(FROM_HERE, run_loop.QuitClosure()); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); run_loop.Run(); // Update the IME status and verify if our IME backend sends an IPC message // to notify layout bounds of the EditContext. main_widget()->UpdateTextInputState(); - auto params = ProcessAndReadIPC<WidgetHostMsg_TextInputStateChanged>(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); blink::WebInputMethodController* controller = frame()->GetWebFrame()->GetInputMethodController(); blink::WebRect expected_control_bounds; @@ -1642,10 +1692,152 @@ TEST_F(RenderViewImplTest, ActiveElementGetLayoutBounds) { controller->GetLayoutBounds(&expected_control_bounds, &temp_selection_bounds); main_widget()->ConvertViewportToWindow(&expected_control_bounds); blink::WebRect actual_active_element_control_bounds( - std::get<0>(params).edit_context_control_bounds.value()); + updated_states()[0]->edit_context_control_bounds.value()); EXPECT_EQ(actual_active_element_control_bounds, expected_control_bounds); } +TEST_F(RenderViewImplTextInputStateChanged, VirtualKeyboardPolicyAuto) { + // Load an HTML page consisting of one input field. + LoadHTML( + "<html>" + "<head>" + "</head>" + "<body>" + "<input id=\"test\" type=\"text\"></input>" + "</body>" + "</html>"); + ClearState(); + // Set focus on the editable element. + ExecuteJavaScriptForTests("document.getElementById('test').focus();"); + // This RunLoop is waiting for focus to be processed for the active element. + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); + run_loop.Run(); + // Update the text input state and verify the virtualkeyboardpolicy attribute + // value. + main_widget()->UpdateTextInputState(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_EQ(updated_states()[0]->vk_policy, + ui::mojom::VirtualKeyboardPolicy::AUTO); +} + +TEST_F(RenderViewImplTextInputStateChanged, VirtualKeyboardPolicyAutoToManual) { + // Load an HTML page consisting of one input field. + LoadHTML( + "<html>" + "<head>" + "</head>" + "<body>" + "<input id=\"test\" type=\"text\" " + "virtualkeyboardpolicy=\"manual\"></input>" + "</body>" + "</html>"); + ClearState(); + // Set focus on the editable element. + ExecuteJavaScriptForTests("document.getElementById('test').focus();"); + // This RunLoop is waiting for focus to be processed for the active element. + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); + run_loop.Run(); + // Update the IME status and verify if our IME backend sends an IPC message + // to notify virtualkeyboardpolicy change of the focused element. + main_widget()->UpdateTextInputState(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_EQ(updated_states()[0]->vk_policy, + ui::mojom::VirtualKeyboardPolicy::MANUAL); + EXPECT_EQ(updated_states()[0]->last_vk_visibility_request, + ui::mojom::VirtualKeyboardVisibilityRequest::NONE); +} + +TEST_F(RenderViewImplTextInputStateChanged, + VirtualKeyboardPolicyManualAndShowHideAPIsCalled) { + // Load an HTML page consisting of two input fields. + LoadHTML( + "<html>" + "<head>" + "</head>" + "<body>" + "<input id=\"test1\" type=\"text\" " + "virtualkeyboardpolicy=\"manual\"></input>" + "<input id=\"test2\" type=\"text\" " + "virtualkeyboardpolicy=\"manual\"></input>" + "</body>" + "</html>"); + ExecuteJavaScriptForTests( + "document.getElementById('test2').focus(); " + "navigator.virtualKeyboard.show();"); + // This RunLoop is waiting for focus to be processed for the active element. + base::RunLoop run_loop1; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop1.QuitClosure()); + run_loop1.Run(); + // Update the IME status and verify if our IME backend sends an IPC message + // to notify virtualkeyboardpolicy change of the focused element and the show + // API call. + main_widget()->UpdateTextInputState(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_EQ(updated_states()[0]->vk_policy, + ui::mojom::VirtualKeyboardPolicy::MANUAL); + EXPECT_EQ(updated_states()[0]->last_vk_visibility_request, + ui::mojom::VirtualKeyboardVisibilityRequest::NONE); + ExecuteJavaScriptForTests( + "document.getElementById('test1').focus(); " + "navigator.virtualKeyboard.hide();"); + base::RunLoop run_loop2; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop2.QuitClosure()); + run_loop2.Run(); + ClearState(); + // Update the IME status and verify if our IME backend sends an IPC message + // to notify virtualkeyboardpolicy change of the focused element and the hide + // API call. + main_widget()->UpdateTextInputState(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_EQ(updated_states()[0]->vk_policy, + ui::mojom::VirtualKeyboardPolicy::MANUAL); + EXPECT_EQ(updated_states()[0]->last_vk_visibility_request, + ui::mojom::VirtualKeyboardVisibilityRequest::HIDE); +} + +TEST_F(RenderViewImplTextInputStateChanged, + VirtualKeyboardPolicyAutoAndShowHideAPIsCalled) { + // Load an HTML page consisting of one input field. + LoadHTML( + "<html>" + "<head>" + "</head>" + "<body>" + "<input id=\"test1\" type=\"text\" " + "virtualkeyboardpolicy=\"auto\"></input>" + "</body>" + "</html>"); + render_thread_->sink().ClearMessages(); + ExecuteJavaScriptForTests( + "document.getElementById('test1').focus(); " + "navigator.virtualKeyboard.show();"); + // This RunLoop is waiting for focus to be processed for the active element. + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); + run_loop.Run(); + // Update the IME status and verify if our IME backend sends an IPC message + // to notify virtualkeyboardpolicy change of the focused element and the show + // API call. + main_widget()->UpdateTextInputState(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, updated_states().size()); + EXPECT_EQ(updated_states()[0]->vk_policy, + ui::mojom::VirtualKeyboardPolicy::AUTO); + EXPECT_EQ(updated_states()[0]->last_vk_visibility_request, + ui::mojom::VirtualKeyboardVisibilityRequest::NONE); +} + // Test that our IME backend can compose CJK words. // Our IME front-end sends many platform-independent messages to the IME backend // while it composes CJK words. This test sends the minimal messages captured @@ -1739,31 +1931,31 @@ TEST_F(RenderViewImplTest, ImeComposition) { case IME_SETFOCUS: // Update the window focus. - main_widget()->OnSetFocus(ime_message->enable); + GetWidgetInputHandler()->SetFocus(ime_message->enable); break; case IME_SETCOMPOSITION: - main_widget()->OnImeSetComposition( + GetWidgetInputHandler()->ImeSetComposition( base::WideToUTF16(ime_message->ime_string), - std::vector<blink::WebImeTextSpan>(), gfx::Range::InvalidRange(), + std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), ime_message->selection_start, ime_message->selection_end); break; case IME_COMMITTEXT: - main_widget()->OnImeCommitText( + GetWidgetInputHandler()->ImeCommitText( base::WideToUTF16(ime_message->ime_string), - std::vector<blink::WebImeTextSpan>(), gfx::Range::InvalidRange(), - 0); + std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0, + base::DoNothing()); break; case IME_FINISHCOMPOSINGTEXT: - main_widget()->OnImeFinishComposingText(false); + GetWidgetInputHandler()->ImeFinishComposingText(false); break; case IME_CANCELCOMPOSITION: - main_widget()->OnImeSetComposition(base::string16(), - std::vector<blink::WebImeTextSpan>(), - gfx::Range::InvalidRange(), 0, 0); + GetWidgetInputHandler()->ImeSetComposition( + base::string16(), std::vector<ui::ImeTextSpan>(), + gfx::Range::InvalidRange(), 0, 0); break; } @@ -1806,13 +1998,13 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) { base::i18n::TextDirection direction; const wchar_t* expected_result; } kTextDirection[] = { - {base::i18n::RIGHT_TO_LEFT, L"rtl,rtl"}, - {base::i18n::LEFT_TO_RIGHT, L"ltr,ltr"}, + {base::i18n::TextDirection::RIGHT_TO_LEFT, L"rtl,rtl"}, + {base::i18n::TextDirection::LEFT_TO_RIGHT, L"ltr,ltr"}, }; for (auto& test_case : kTextDirection) { // Set the text direction of the <textarea> element. ExecuteJavaScriptForTests("document.getElementById('test').focus();"); - ReceiveSetTextDirection(main_widget(), test_case.direction); + GetMainFrame()->SetTextDirectionForTesting(test_case.direction); // Write the values of its DOM 'dir' attribute and its CSS 'direction' // property to the <div> element. @@ -2002,47 +2194,52 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { LoadHTML("<textarea id=\"test\" cols=\"100\"></textarea>"); ExecuteJavaScriptForTests("document.getElementById('test').focus();"); + auto* widget_input_handler = GetWidgetInputHandler(); const base::string16 empty_string; - const std::vector<blink::WebImeTextSpan> empty_ime_text_span; + const std::vector<ui::ImeTextSpan> empty_ime_text_span; std::vector<gfx::Rect> bounds; - main_widget()->OnSetFocus(true); + widget_input_handler->SetFocus(true); // ASCII composition const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo"); - main_widget()->OnImeSetComposition(ascii_composition, empty_ime_text_span, - gfx::Range::InvalidRange(), 0, 0); - main_widget()->GetCompositionCharacterBounds(&bounds); + widget_input_handler->ImeSetComposition( + ascii_composition, empty_ime_text_span, gfx::Range::InvalidRange(), 0, 0); + bounds = LastCompositionBounds(); ASSERT_EQ(ascii_composition.size(), bounds.size()); for (const gfx::Rect& r : bounds) EXPECT_LT(0, r.width()); - main_widget()->OnImeCommitText(empty_string, - std::vector<blink::WebImeTextSpan>(), - gfx::Range::InvalidRange(), 0); + widget_input_handler->ImeCommitText( + empty_string, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), + 0, base::DoNothing()); // Non surrogate pair unicode character. const base::string16 unicode_composition = base::UTF8ToUTF16( "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"); - main_widget()->OnImeSetComposition(unicode_composition, empty_ime_text_span, - gfx::Range::InvalidRange(), 0, 0); - main_widget()->GetCompositionCharacterBounds(&bounds); + widget_input_handler->ImeSetComposition(unicode_composition, + empty_ime_text_span, + gfx::Range::InvalidRange(), 0, 0); + bounds = LastCompositionBounds(); ASSERT_EQ(unicode_composition.size(), bounds.size()); for (const gfx::Rect& r : bounds) EXPECT_LT(0, r.width()); - main_widget()->OnImeCommitText(empty_string, empty_ime_text_span, - gfx::Range::InvalidRange(), 0); + widget_input_handler->ImeCommitText(empty_string, empty_ime_text_span, + gfx::Range::InvalidRange(), 0, + base::DoNothing()); // Surrogate pair character. const base::string16 surrogate_pair_char = base::UTF8ToUTF16("\xF0\xA0\xAE\x9F"); - main_widget()->OnImeSetComposition(surrogate_pair_char, empty_ime_text_span, - gfx::Range::InvalidRange(), 0, 0); - main_widget()->GetCompositionCharacterBounds(&bounds); + widget_input_handler->ImeSetComposition(surrogate_pair_char, + empty_ime_text_span, + gfx::Range::InvalidRange(), 0, 0); + bounds = LastCompositionBounds(); ASSERT_EQ(surrogate_pair_char.size(), bounds.size()); EXPECT_LT(0, bounds[0].width()); EXPECT_EQ(0, bounds[1].width()); - main_widget()->OnImeCommitText(empty_string, empty_ime_text_span, - gfx::Range::InvalidRange(), 0); + widget_input_handler->ImeCommitText(empty_string, empty_ime_text_span, + gfx::Range::InvalidRange(), 0, + base::DoNothing()); // Mixed string. const base::string16 surrogate_pair_mixed_composition = @@ -2051,10 +2248,10 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { const size_t utf16_length = 8UL; const bool is_surrogate_pair_empty_rect[8] = { false, true, false, false, true, false, false, true }; - main_widget()->OnImeSetComposition(surrogate_pair_mixed_composition, - empty_ime_text_span, - gfx::Range::InvalidRange(), 0, 0); - main_widget()->GetCompositionCharacterBounds(&bounds); + widget_input_handler->ImeSetComposition(surrogate_pair_mixed_composition, + empty_ime_text_span, + gfx::Range::InvalidRange(), 0, 0); + bounds = LastCompositionBounds(); ASSERT_EQ(utf16_length, bounds.size()); for (size_t i = 0; i < utf16_length; ++i) { if (is_surrogate_pair_empty_rect[i]) { @@ -2063,8 +2260,9 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { EXPECT_LT(0, bounds[i].width()); } } - main_widget()->OnImeCommitText(empty_string, empty_ime_text_span, - gfx::Range::InvalidRange(), 0); + widget_input_handler->ImeCommitText(empty_string, empty_ime_text_span, + gfx::Range::InvalidRange(), 0, + base::DoNothing()); } #endif @@ -2077,10 +2275,12 @@ TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) { "<input id=\"test1\" value=\"some test text hello\"></input>" "</body>" "</html>"); + auto* frame_widget_input_handler = GetFrameWidgetInputHandler(); ExecuteJavaScriptForTests("document.getElementById('test1').focus();"); - frame()->SetEditableSelectionOffsets(4, 8); + frame_widget_input_handler->SetEditableSelectionOffsets(4, 8); const std::vector<ui::ImeTextSpan> empty_ime_text_span; - frame()->SetCompositionFromExistingText(7, 10, empty_ime_text_span); + frame_widget_input_handler->SetCompositionFromExistingText( + 7, 10, empty_ime_text_span); base::RunLoop().RunUntilIdle(); blink::WebInputMethodController* controller = frame()->GetWebFrame()->GetInputMethodController(); @@ -2089,7 +2289,7 @@ TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) { EXPECT_EQ(8, info.selection_end); EXPECT_EQ(7, info.composition_start); EXPECT_EQ(10, info.composition_end); - frame()->CollapseSelection(); + frame_widget_input_handler->CollapseSelection(); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ(8, info.selection_start); @@ -2105,9 +2305,10 @@ TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) { "<input id=\"test1\" value=\"abcdefghijklmnopqrstuvwxyz\"></input>" "</body>" "</html>"); + auto* frame_widget_input_handler = GetFrameWidgetInputHandler(); ExecuteJavaScriptForTests("document.getElementById('test1').focus();"); - frame()->SetEditableSelectionOffsets(10, 10); - frame()->ExtendSelectionAndDelete(3, 4); + frame_widget_input_handler->SetEditableSelectionOffsets(10, 10); + frame_widget_input_handler->ExtendSelectionAndDelete(3, 4); base::RunLoop().RunUntilIdle(); blink::WebInputMethodController* controller = frame()->GetWebFrame()->GetInputMethodController(); @@ -2115,8 +2316,8 @@ TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) { EXPECT_EQ("abcdefgopqrstuvwxyz", info.value); EXPECT_EQ(7, info.selection_start); EXPECT_EQ(7, info.selection_end); - frame()->SetEditableSelectionOffsets(4, 8); - frame()->ExtendSelectionAndDelete(2, 5); + frame_widget_input_handler->SetEditableSelectionOffsets(4, 8); + frame_widget_input_handler->ExtendSelectionAndDelete(2, 5); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ("abuvwxyz", info.value); @@ -2136,8 +2337,9 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingText) { "</html>"); ExecuteJavaScriptForTests("document.getElementById('test1').focus();"); - frame()->SetEditableSelectionOffsets(10, 10); - frame()->DeleteSurroundingText(3, 4); + auto* frame_widget_input_handler = GetFrameWidgetInputHandler(); + frame_widget_input_handler->SetEditableSelectionOffsets(10, 10); + frame_widget_input_handler->DeleteSurroundingText(3, 4); base::RunLoop().RunUntilIdle(); blink::WebInputMethodController* controller = frame()->GetWebFrame()->GetInputMethodController(); @@ -2146,30 +2348,30 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingText) { EXPECT_EQ(7, info.selection_start); EXPECT_EQ(7, info.selection_end); - frame()->SetEditableSelectionOffsets(4, 8); - frame()->DeleteSurroundingText(2, 5); + frame_widget_input_handler->SetEditableSelectionOffsets(4, 8); + frame_widget_input_handler->DeleteSurroundingText(2, 5); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ("abefgouvwxyz", info.value); EXPECT_EQ(2, info.selection_start); EXPECT_EQ(6, info.selection_end); - frame()->SetEditableSelectionOffsets(5, 5); - frame()->DeleteSurroundingText(10, 0); + frame_widget_input_handler->SetEditableSelectionOffsets(5, 5); + frame_widget_input_handler->DeleteSurroundingText(10, 0); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ("ouvwxyz", info.value); EXPECT_EQ(0, info.selection_start); EXPECT_EQ(0, info.selection_end); - frame()->DeleteSurroundingText(0, 10); + frame_widget_input_handler->DeleteSurroundingText(0, 10); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ("", info.value); EXPECT_EQ(0, info.selection_start); EXPECT_EQ(0, info.selection_end); - frame()->DeleteSurroundingText(10, 10); + frame_widget_input_handler->DeleteSurroundingText(10, 10); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ("", info.value); @@ -2193,8 +2395,9 @@ TEST_F(RenderViewImplTest, MAYBE_OnDeleteSurroundingTextInCodePoints) { "<input id=\"test1\" value=\"ab🏆 cdef🏆 gh\">"); ExecuteJavaScriptForTests("document.getElementById('test1').focus();"); - frame()->SetEditableSelectionOffsets(4, 4); - frame()->DeleteSurroundingTextInCodePoints(2, 2); + auto* frame_widget_input_handler = GetFrameWidgetInputHandler(); + frame_widget_input_handler->SetEditableSelectionOffsets(4, 4); + frame_widget_input_handler->DeleteSurroundingTextInCodePoints(2, 2); base::RunLoop().RunUntilIdle(); blink::WebInputMethodController* controller = frame()->GetWebFrame()->GetInputMethodController(); @@ -2204,8 +2407,8 @@ TEST_F(RenderViewImplTest, MAYBE_OnDeleteSurroundingTextInCodePoints) { EXPECT_EQ(1, info.selection_start); EXPECT_EQ(1, info.selection_end); - frame()->SetEditableSelectionOffsets(1, 3); - frame()->DeleteSurroundingTextInCodePoints(1, 4); + frame_widget_input_handler->SetEditableSelectionOffsets(1, 3); + frame_widget_input_handler->DeleteSurroundingTextInCodePoints(1, 4); base::RunLoop().RunUntilIdle(); info = controller->TextInputInfo(); EXPECT_EQ("deh", info.value); @@ -2251,33 +2454,61 @@ TEST_F(RenderViewImplTest, BasicRenderFrame) { EXPECT_TRUE(view()->main_render_frame_); } -TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) { +class MessageOrderFakeRenderWidgetHost : public FakeRenderWidgetHost, + public IPC::Listener { + public: + void TextInputStateChanged(ui::mojom::TextInputStatePtr state) override { + message_counter_++; + last_input_type_ = message_counter_; + } + + ~MessageOrderFakeRenderWidgetHost() override {} + + bool OnMessageReceived(const IPC::Message& message) override { + if (message.type() == FrameHostMsg_SelectionChanged::ID) { + base::RunLoop().RunUntilIdle(); + message_counter_++; + last_selection_ = message_counter_; + } + return false; + } + + uint32_t message_counter_ = 0; + uint32_t last_selection_ = 0; + uint32_t last_input_type_ = 0; +}; + +class RenderViewImplTextInputMessageOrder : public RenderViewImplTest { + public: + std::unique_ptr<FakeRenderWidgetHost> CreateRenderWidgetHost() override { + auto host = std::make_unique<MessageOrderFakeRenderWidgetHost>(); + render_thread_->sink().AddFilter(host.get()); + return host; + } + + MessageOrderFakeRenderWidgetHost* GetMessageOrderFakeRenderWidgetHost() { + return static_cast<MessageOrderFakeRenderWidgetHost*>( + render_widget_host_.get()); + } +}; + +TEST_F(RenderViewImplTextInputMessageOrder, MessageOrderInDidChangeSelection) { LoadHTML("<textarea id=\"test\"></textarea>"); main_widget()->SetHandlingInputEvent(true); ExecuteJavaScriptForTests("document.getElementById('test').focus();"); - bool is_input_type_called = false; - bool is_selection_called = false; - size_t last_input_type = 0; - size_t last_selection = 0; - - for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) { - const uint32_t type = render_thread_->sink().GetMessageAt(i)->type(); - if (type == WidgetHostMsg_TextInputStateChanged::ID) { - is_input_type_called = true; - last_input_type = i; - } else if (type == FrameHostMsg_SelectionChanged::ID) { - is_selection_called = true; - last_selection = i; - } - } + uint32_t last_input_type = + GetMessageOrderFakeRenderWidgetHost()->last_input_type_; + uint32_t last_selection = + GetMessageOrderFakeRenderWidgetHost()->last_selection_; - EXPECT_TRUE(is_input_type_called); - EXPECT_TRUE(is_selection_called); + EXPECT_NE(0u, last_input_type); + EXPECT_NE(0u, last_selection); // InputTypeChange shold be called earlier than SelectionChanged. EXPECT_LT(last_input_type, last_selection); + render_thread_->sink().RemoveFilter(GetMessageOrderFakeRenderWidgetHost()); } class RendererErrorPageTest : public RenderViewImplTest { @@ -2952,21 +3183,21 @@ TEST_F(RenderViewImplEnableZoomForDSFTest, LoadHTML("<textarea id=\"test\"></textarea>"); ExecuteJavaScriptForTests("document.getElementById('test').focus();"); + auto* widget_input_handler = GetWidgetInputHandler(); const base::string16 empty_string; - const std::vector<blink::WebImeTextSpan> empty_ime_text_span; + const std::vector<ui::ImeTextSpan> empty_ime_text_span; std::vector<gfx::Rect> bounds_at_1x; - main_widget()->OnSetFocus(true); + widget_input_handler->SetFocus(true); // ASCII composition const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo"); - main_widget()->OnImeSetComposition(ascii_composition, empty_ime_text_span, - gfx::Range::InvalidRange(), 0, 0); - main_widget()->GetCompositionCharacterBounds(&bounds_at_1x); + widget_input_handler->ImeSetComposition( + ascii_composition, empty_ime_text_span, gfx::Range::InvalidRange(), 0, 0); + bounds_at_1x = LastCompositionBounds(); ASSERT_EQ(ascii_composition.size(), bounds_at_1x.size()); SetDeviceScaleFactor(2.f); - std::vector<gfx::Rect> bounds_at_2x; - main_widget()->GetCompositionCharacterBounds(&bounds_at_2x); + std::vector<gfx::Rect> bounds_at_2x = LastCompositionBounds(); ASSERT_EQ(bounds_at_1x.size(), bounds_at_2x.size()); for (size_t i = 0; i < bounds_at_1x.size(); i++) { const gfx::Rect& b1 = bounds_at_1x[i]; diff --git a/chromium/content/renderer/render_view_browsertest_mac.mm b/chromium/content/renderer/render_view_browsertest_mac.mm index 60598036c03..4ed49d1a4d9 100644 --- a/chromium/content/renderer/render_view_browsertest_mac.mm +++ b/chromium/content/renderer/render_view_browsertest_mac.mm @@ -24,7 +24,6 @@ #include <Cocoa/Cocoa.h> using blink::WebFrameContentDumper; -using blink::WebImeTextSpan; namespace content { diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc index 6fc04eb140e..efab6135265 100644 --- a/chromium/content/renderer/render_view_impl.cc +++ b/chromium/content/renderer/render_view_impl.cc @@ -65,7 +65,6 @@ #include "content/public/renderer/window_features_converter.h" #include "content/renderer/drop_data_builder.h" #include "content/renderer/history_serialization.h" -#include "content/renderer/ime_event_guard.h" #include "content/renderer/internal_document_state_data.h" #include "content/renderer/loader/request_extra_data.h" #include "content/renderer/media/audio/audio_device_factory.h" @@ -75,7 +74,6 @@ #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/renderer_blink_platform_impl.h" -#include "content/renderer/savable_resources.h" #include "content/renderer/v8_value_converter_impl.h" #include "content/renderer/web_ui_extension_data.h" #include "media/audio/audio_output_device.h" @@ -440,8 +438,9 @@ void RenderViewImpl::Initialize( bool has_show_callback = !!show_callback; #endif - WebFrame* opener_frame = - RenderFrameImpl::ResolveWebFrame(params->opener_frame_route_id); + auto opener_frame_token = + params->opener_frame_token.value_or(base::UnguessableToken()); + auto* opener_frame = WebFrame::FromFrameToken(opener_frame_token); // The newly created webview_ is owned by this instance. webview_ = WebView::Create(this, params->hidden, @@ -462,7 +461,7 @@ void RenderViewImpl::Initialize( this, compositor_deps, opener_frame, ¶ms, std::move(show_callback)); } else { RenderFrameProxy::CreateFrameProxy( - params->proxy_routing_id, GetRoutingID(), opener_frame, + params->proxy_routing_id, GetRoutingID(), opener_frame_token, MSG_ROUTING_NONE, params->replicated_frame_state, params->main_frame_frame_token, params->devtools_main_frame_token); } @@ -640,11 +639,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, settings->SetAntialiasedClips2dCanvasEnabled( prefs.antialiased_clips_2d_canvas_enabled); - // Set MSAA sample count for 2d canvas if requested on the command line (or - // default value if not). - settings->SetAccelerated2dCanvasMSAASampleCount( - prefs.accelerated_2d_canvas_msaa_sample_count); - // Tabs to link is not part of the settings. WebCore calls // ChromeClient::tabsToLinks which is part of the glue code. web_view->SetTabsToLinks(prefs.tabs_to_links); @@ -683,9 +677,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, settings->SetEnableTouchAdjustment(prefs.touch_adjustment_enabled); settings->SetBarrelButtonForDragEnabled(prefs.barrel_button_for_drag_enabled); - settings->SetShouldRespectImageOrientation( - prefs.should_respect_image_orientation); - settings->SetEditingBehavior( static_cast<WebSettings::EditingBehavior>(prefs.editing_behavior)); @@ -1186,11 +1177,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(PageMsg_SetHistoryOffsetAndLength, OnSetHistoryOffsetAndLength) IPC_MESSAGE_HANDLER(PageMsg_AudioStateChanged, OnAudioStateChanged) - IPC_MESSAGE_HANDLER(PageMsg_SetPageFrozen, SetPageFrozen) - IPC_MESSAGE_HANDLER(PageMsg_PutPageIntoBackForwardCache, - PutPageIntoBackForwardCache) - IPC_MESSAGE_HANDLER(PageMsg_RestorePageFromBackForwardCache, - RestorePageFromBackForwardCache) IPC_MESSAGE_HANDLER(PageMsg_UpdateTextAutosizerPageInfoForRemoteMainFrames, OnTextAutosizerPageInfoChanged) IPC_MESSAGE_HANDLER(PageMsg_SetRendererPrefs, OnSetRendererPrefs) @@ -1296,7 +1282,7 @@ WebView* RenderViewImpl::CreateView( // disagrees. mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New(); - view_params->opener_frame_route_id = creator_frame->GetRoutingID(); + view_params->opener_frame_token = creator->GetFrameToken(); DCHECK_EQ(GetRoutingID(), creator_frame->render_view()->GetRoutingID()); view_params->window_was_created_with_opener = true; @@ -1309,6 +1295,7 @@ WebView* RenderViewImpl::CreateView( view_params->frame_widget = std::move(reply->frame_widget); view_params->widget_host = std::move(reply->widget_host); view_params->widget = std::move(reply->widget), + view_params->blink_page_broadcast = std::move(reply->page_broadcast); view_params->main_frame_interface_bundle = mojom::DocumentScopedInterfaceBundle::New( std::move(reply->main_frame_interface_bundle->interface_provider), @@ -1340,9 +1327,9 @@ WebView* RenderViewImpl::CreateView( creator->GetTaskRunner(blink::TaskType::kInternalDefault)); if (reply->wait_for_debugger) { - blink::WebLocalFrame* main_frame = - view->GetWebView()->MainFrame()->ToWebLocalFrame(); - main_frame->WaitForDebuggerWhenShown(); + blink::WebFrameWidget* frame_widget = + view->GetMainRenderFrame()->GetLocalRootWebFrameWidget(); + frame_widget->WaitForDebuggerWhenShown(); } return view->GetWebView(); @@ -1350,10 +1337,6 @@ WebView* RenderViewImpl::CreateView( blink::WebPagePopup* RenderViewImpl::CreatePopup( blink::WebLocalFrame* creator) { - mojo::PendingRemote<mojom::Widget> widget_channel; - mojo::PendingReceiver<mojom::Widget> widget_channel_receiver = - widget_channel.InitWithNewPipeAndPassReceiver(); - mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget; mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver = blink_widget.InitWithNewEndpointAndPassReceiver(); @@ -1367,8 +1350,8 @@ blink::WebPagePopup* RenderViewImpl::CreatePopup( int32_t widget_routing_id = MSG_ROUTING_NONE; bool success = RenderFrameImpl::FromWebFrame(creator)->GetFrameHost()->CreateNewWidget( - std::move(widget_channel), std::move(blink_widget_host_receiver), - std::move(blink_widget), &widget_routing_id); + std::move(blink_widget_host_receiver), std::move(blink_widget), + &widget_routing_id); if (!success) { // When the renderer is being killed the mojo message will fail. return nullptr; @@ -1383,7 +1366,7 @@ blink::WebPagePopup* RenderViewImpl::CreatePopup( RenderWidget* popup_widget = RenderWidget::CreateForPopup( widget_routing_id, opener_render_widget->compositor_deps(), /*hidden=*/false, - /*never_composited=*/false, std::move(widget_channel_receiver)); + /*never_composited=*/false); // The returned WebPagePopup is self-referencing, so the pointer here is not // an owning pointer. It is de-referenced by calling Close(). @@ -1438,7 +1421,7 @@ void RenderViewImpl::PrintPage(WebLocalFrame* frame) { RenderWidget* render_widget = render_frame->GetLocalRootRenderWidget(); render_frame->ScriptedPrint( - render_widget->input_handler().handling_input_event()); + render_widget->GetWebWidget()->HandlingInputEvent()); } bool RenderViewImpl::SetZoomLevel(double zoom_level) { @@ -1679,16 +1662,6 @@ bool RenderViewImpl::GetContentStateImmediately() { return send_content_state_immediately_; } -void RenderViewImpl::ApplyPageVisibilityState( - PageVisibilityState visibility_state, - bool initial_setting) { - GetWebView()->SetVisibilityState(visibility_state, initial_setting); - for (auto& observer : observers_) - observer.OnPageVisibilityChanged(visibility_state); - // Note: RenderWidget visibility is separately set from the IPC handlers, and - // does not change when tests override the visibility of the Page. -} - void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) { webkit_preferences_ = prefs; ApplyWebPreferences(webkit_preferences_, GetWebView()); @@ -1745,17 +1718,6 @@ void RenderViewImpl::SetPageFrozen(bool frozen) { GetWebView()->SetPageFrozen(frozen); } -void RenderViewImpl::PutPageIntoBackForwardCache() { - if (GetWebView()) - GetWebView()->PutPageIntoBackForwardCache(); -} - -void RenderViewImpl::RestorePageFromBackForwardCache( - base::TimeTicks navigation_start) { - if (GetWebView()) - GetWebView()->RestorePageFromBackForwardCache(navigation_start); -} - // This function receives TextAutosizerPageInfo from the main frame's renderer // and makes it available to other renderers with frames on the same page. void RenderViewImpl::OnTextAutosizerPageInfoChanged( @@ -1780,20 +1742,6 @@ void RenderViewImpl::DidAutoResize(const blink::WebSize& newSize) { main_render_frame_->GetLocalRootRenderWidget()->DidAutoResize(newSize); } -void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) { - // We only allow focus to move to this RenderView when the request comes from - // a user gesture. (See also https://bugs.webkit.org/show_bug.cgi?id=33389.) - if (calling_frame && calling_frame->HasTransientUserActivation()) { - Send(new ViewHostMsg_Focus(GetRoutingID())); - - // Tattle on the frame that called |window.focus()|. - RenderFrameImpl* calling_render_frame = - RenderFrameImpl::FromWebFrame(calling_frame); - if (calling_render_frame) - calling_render_frame->FrameDidCallFocus(); - } -} - #if defined(OS_ANDROID) void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) { if (!main_render_frame_) diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h index c91cfca2f65..79ffb7a4a0e 100644 --- a/chromium/content/renderer/render_view_impl.h +++ b/chromium/content/renderer/render_view_impl.h @@ -234,7 +234,6 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient, int HistoryBackListCount() override; int HistoryForwardListCount() override; void DidAutoResize(const blink::WebSize& newSize) override; - void DidFocus(blink::WebLocalFrame* calling_frame) override; bool CanHandleGestureEvent() override; bool AllowPopupsDuringPageUnload() override; void OnPageVisibilityChanged(PageVisibilityState visibility) override; @@ -268,12 +267,6 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient, const mojom::CreateViewParams& params); ~RenderViewImpl() override; - // Called when Page visibility is changed, to update the View/Page in blink. - // This is separate from the IPC handlers as tests may call this and need to - // be able to specify |initial_setting| where IPC handlers do not. - void ApplyPageVisibilityState(PageVisibilityState visibility_state, - bool initial_setting); - private: // For unit tests. friend class DevToolsAgentTest; @@ -405,8 +398,6 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient, // Page message handlers ----------------------------------------------------- void SetPageFrozen(bool frozen); - void PutPageIntoBackForwardCache(); - void RestorePageFromBackForwardCache(base::TimeTicks navigation_start); void OnTextAutosizerPageInfoChanged( const blink::WebTextAutosizerPageInfo& page_info); void OnSetInsidePortal(bool inside_portal); diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc index 1bec58e292d..30e6638b9c5 100644 --- a/chromium/content/renderer/render_widget.cc +++ b/chromium/content/renderer/render_widget.cc @@ -19,6 +19,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" #include "base/metrics/histogram_macros.h" +#include "base/optional.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -43,7 +44,6 @@ #include "content/common/drag_event_source_info.h" #include "content/common/drag_messages.h" #include "content/common/render_message_filter.mojom.h" -#include "content/common/text_input_state.h" #include "content/common/widget_messages.h" #include "content/public/common/content_client.h" #include "content/public/common/content_features.h" @@ -77,14 +77,17 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "ppapi/buildflags/buildflags.h" #include "skia/ext/platform_canvas.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/input/web_input_event_attribution.h" #include "third_party/blink/public/common/input/web_mouse_event.h" +#include "third_party/blink/public/common/page/web_drag_operation.h" +#include "third_party/blink/public/common/switches.h" #include "third_party/blink/public/platform/file_path_conversion.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/scheduler/web_widget_scheduler.h" #include "third_party/blink/public/platform/web_drag_data.h" -#include "third_party/blink/public/platform/web_drag_operation.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_runtime_features.h" #include "third_party/blink/public/platform/web_size.h" @@ -106,6 +109,7 @@ #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/events/base_event_utils.h" +#include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size_conversions.h" @@ -127,7 +131,6 @@ #include "third_party/skia/include/core/SkPixelRef.h" #endif // defined(OS_POSIX) -using blink::WebImeTextSpan; using blink::WebDeviceEmulationParams; using blink::WebDragOperation; using blink::WebDragOperationsMask; @@ -159,16 +162,11 @@ namespace { RenderWidget::CreateRenderWidgetFunction g_create_render_widget_for_frame = nullptr; -using RoutingIDWidgetMap = std::map<int32_t, RenderWidget*>; -base::LazyInstance<RoutingIDWidgetMap>::Leaky g_routing_id_widget_map = - LAZY_INSTANCE_INITIALIZER; - const base::Feature kUnpremultiplyAndDitherLowBitDepthTiles = { "UnpremultiplyAndDitherLowBitDepthTiles", base::FEATURE_ENABLED_BY_DEFAULT}; typedef std::map<std::string, ui::TextInputMode> TextInputModeMap; -static const int kInvalidNextPreviousFlagsValue = -1; static const char* kOOPIF = "OOPIF"; static const char* kRenderer = "Renderer"; @@ -210,14 +208,6 @@ class WebWidgetLockTarget : public content::MouseLockDispatcher::LockTarget { RenderWidget* render_widget_; }; -bool IsDateTimeInput(ui::TextInputType type) { - return type == ui::TEXT_INPUT_TYPE_DATE || - type == ui::TEXT_INPUT_TYPE_DATE_TIME || - type == ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL || - type == ui::TEXT_INPUT_TYPE_MONTH || - type == ui::TEXT_INPUT_TYPE_TIME || type == ui::TEXT_INPUT_TYPE_WEEK; -} - WebDragData DropMetaDataToWebDragData( const std::vector<DropData::Metadata>& drop_meta_data) { std::vector<WebDragData::Item> item_list; @@ -260,7 +250,6 @@ WebDragData DropMetaDataToWebDragData( } WebDragData result; - result.Initialize(); result.SetItems(item_list); return result; } @@ -273,11 +262,11 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) { DCHECK(drop_data.file_contents.empty()); DCHECK(drop_data.file_contents_content_disposition.empty()); - if (!drop_data.text.is_null()) { + if (drop_data.text) { WebDragData::Item item; item.storage_type = WebDragData::Item::kStorageTypeString; item.string_type = WebString::FromUTF8(ui::kMimeTypeText); - item.string_data = WebString::FromUTF16(drop_data.text.string()); + item.string_data = WebString::FromUTF16(*drop_data.text); item_list.push_back(item); } @@ -290,11 +279,11 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) { item_list.push_back(item); } - if (!drop_data.html.is_null()) { + if (drop_data.html) { WebDragData::Item item; item.storage_type = WebDragData::Item::kStorageTypeString; item.string_type = WebString::FromUTF8(ui::kMimeTypeHTML); - item.string_data = WebString::FromUTF16(drop_data.html.string()); + item.string_data = WebString::FromUTF16(*drop_data.html); item.base_url = drop_data.html_base_url; item_list.push_back(item); } @@ -326,25 +315,19 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) { } WebDragData result; - result.Initialize(); result.SetItems(item_list); result.SetFilesystemId(WebString::FromUTF16(drop_data.filesystem_id)); return result; } -ui::TextInputType ConvertWebTextInputType(blink::WebTextInputType type) { +#if BUILDFLAG(ENABLE_PLUGINS) +blink::WebTextInputType ConvertTextInputType(ui::TextInputType type) { // Check the type is in the range representable by ui::TextInputType. DCHECK_LE(type, static_cast<int>(ui::TEXT_INPUT_TYPE_MAX)) << "blink::WebTextInputType and ui::TextInputType not synchronized"; - return static_cast<ui::TextInputType>(type); -} - -ui::TextInputMode ConvertWebTextInputMode(blink::WebTextInputMode mode) { - // Check the mode is in the range representable by ui::TextInputMode. - DCHECK_LE(mode, static_cast<int>(ui::TEXT_INPUT_MODE_MAX)) - << "blink::WebTextInputMode and ui::TextInputMode not synchronized"; - return static_cast<ui::TextInputMode>(mode); + return static_cast<blink::WebTextInputType>(type); } +#endif static bool ComputePreferCompositingToLCDText( CompositorDependencies* compositor_deps, @@ -374,6 +357,30 @@ static bool ComputePreferCompositingToLCDText( #endif } +viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebHitTestResult& result) { + const blink::WebNode& node = result.GetNode(); + DCHECK(!node.IsNull()); + blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node); + if (!result_frame || !result_frame->IsWebRemoteFrame()) + return viz::FrameSinkId(); + + blink::WebRemoteFrame* remote_frame = result_frame->ToWebRemoteFrame(); + if (remote_frame->IsIgnoredForHitTest() || !result.ContentBoxContainsPoint()) + return viz::FrameSinkId(); + + return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id(); +} + +blink::mojom::DidOverscrollParamsPtr ToOverscrollParams( + const blink::InputHandlerProxy::DidOverscrollParams* params) { + if (!params) + return nullptr; + return blink::mojom::DidOverscrollParams::New( + params->accumulated_overscroll, params->latest_overscroll_delta, + params->current_fling_velocity, params->causal_event_viewport_point, + params->overscroll_behavior); +} + } // namespace // RenderWidget --------------------------------------------------------------- @@ -390,63 +397,40 @@ std::unique_ptr<RenderWidget> RenderWidget::CreateForFrame( bool never_composited) { if (g_create_render_widget_for_frame) { return g_create_render_widget_for_frame(widget_routing_id, compositor_deps, - /*hidden=*/true, never_composited, - mojo::NullReceiver()); + /*hidden=*/true, never_composited); } return std::make_unique<RenderWidget>(widget_routing_id, compositor_deps, - /*hidden=*/true, never_composited, - mojo::NullReceiver()); + /*hidden=*/true, never_composited); } RenderWidget* RenderWidget::CreateForPopup( int32_t widget_routing_id, CompositorDependencies* compositor_deps, bool hidden, - bool never_composited, - mojo::PendingReceiver<mojom::Widget> widget_receiver) { + bool never_composited) { return new RenderWidget(widget_routing_id, compositor_deps, hidden, - never_composited, std::move(widget_receiver)); + never_composited); } RenderWidget::RenderWidget(int32_t widget_routing_id, CompositorDependencies* compositor_deps, bool hidden, - bool never_composited, - mojo::PendingReceiver<mojom::Widget> widget_receiver) + bool never_composited) : routing_id_(widget_routing_id), compositor_deps_(compositor_deps), is_hidden_(hidden), never_composited_(never_composited), - next_previous_flags_(kInvalidNextPreviousFlagsValue), - frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)), - widget_receiver_(this, std::move(widget_receiver)) { + frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)) { DCHECK_NE(routing_id_, MSG_ROUTING_NONE); DCHECK(RenderThread::IsMainThread()); DCHECK(compositor_deps_); - - if (routing_id_ != MSG_ROUTING_NONE) - g_routing_id_widget_map.Get().emplace(routing_id_, this); } RenderWidget::~RenderWidget() { DCHECK(!webwidget_) << "Leaking our WebWidget!"; DCHECK(closing_) << " RenderWidget must be destroyed via RenderWidget::Close()"; - - // TODO(ajwong): Add in check that routing_id_ has been removed from - // g_routing_id_widget_map once the shutdown semantics for RenderWidget - // and RenderViewImpl are rationalized. Currently, too many unit and - // browser tests delete a RenderWidget without correclty going through - // the shutdown. https://crbug.com/545684 -} - -// static -RenderWidget* RenderWidget::FromRoutingID(int32_t routing_id) { - DCHECK(RenderThread::IsMainThread()); - RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer(); - auto it = widgets->find(routing_id); - return it == widgets->end() ? NULL : it->second; } void RenderWidget::InitForPopup(ShowCallback show_callback, @@ -498,8 +482,6 @@ void RenderWidget::Initialize(ShowCallback show_callback, DCHECK_NE(routing_id_, MSG_ROUTING_NONE); DCHECK(web_widget); - input_handler_ = std::make_unique<RenderWidgetInputHandler>(this, this); - show_callback_ = std::move(show_callback); #if defined(OS_MACOSX) @@ -567,19 +549,14 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(WidgetMsg_WasHidden, OnWasHidden) IPC_MESSAGE_HANDLER(WidgetMsg_WasShown, OnWasShown) IPC_MESSAGE_HANDLER(WidgetMsg_SetActive, OnSetActive) - IPC_MESSAGE_HANDLER(WidgetMsg_SetTextDirection, OnSetTextDirection) IPC_MESSAGE_HANDLER(WidgetMsg_SetBounds_ACK, OnRequestSetBoundsAck) IPC_MESSAGE_HANDLER(WidgetMsg_UpdateScreenRects, OnUpdateScreenRects) - IPC_MESSAGE_HANDLER(WidgetMsg_ForceRedraw, OnForceRedraw) IPC_MESSAGE_HANDLER(WidgetMsg_SetViewportIntersection, OnSetViewportIntersection) IPC_MESSAGE_HANDLER(WidgetMsg_WaitForNextFrameForTests, OnWaitNextFrameForTests) IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter) - IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver) - IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave) IPC_MESSAGE_HANDLER(DragMsg_TargetDrop, OnDragTargetDrop) - IPC_MESSAGE_HANDLER(DragMsg_SourceEnded, OnDragSourceEnded) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -600,7 +577,7 @@ bool RenderWidget::Send(IPC::Message* message) { bool RenderWidget::ShouldHandleImeEvents() const { if (delegate()) - return has_focus_; + return GetWebWidget()->HasFocus(); if (for_child_local_root_frame_) { // TODO(ekaramad): We track page focus in all RenderViews on the page but // the RenderWidgets corresponding to child local roots do not get the @@ -733,6 +710,24 @@ void RenderWidget::OnUpdateVisualProperties( if (for_frame()) { SetZoomLevel(visual_properties.zoom_level); + if (root_widget_window_segments_ != + visual_properties.root_widget_window_segments) { + root_widget_window_segments_ = + visual_properties.root_widget_window_segments; + + blink::WebVector<blink::WebRect> web_segments; + web_segments.reserve(root_widget_window_segments_.size()); + for (const auto& segment : root_widget_window_segments_) + web_segments.emplace_back(segment); + + GetWebWidget()->SetWindowSegments(std::move(web_segments)); + + // Propagate changes down to child local root RenderWidgets in other frame + // trees/processes. + for (auto& observer : render_frame_proxies_) + observer.OnRootWindowSegmentsChanged(root_widget_window_segments_); + } + bool capture_sequence_number_changed = visual_properties.capture_sequence_number != last_capture_sequence_number_; @@ -1027,32 +1022,71 @@ void RenderWidget::OnRequestSetBoundsAck() { pending_window_rect_count_--; } -void RenderWidget::OnForceRedraw(int snapshot_id) { - RequestPresentation(base::BindOnce(&RenderWidget::DidPresentForceDrawFrame, - weak_ptr_factory_.GetWeakPtr(), - snapshot_id)); -} - void RenderWidget::RequestPresentation(PresentationTimeCallback callback) { layer_tree_host_->RequestPresentationTimeForNextFrame(std::move(callback)); layer_tree_host_->SetNeedsCommitWithForcedRedraw(); } -void RenderWidget::DidPresentForceDrawFrame( - int snapshot_id, - const gfx::PresentationFeedback& feedback) { - Send(new WidgetHostMsg_ForceRedrawComplete(routing_id(), snapshot_id)); +void RenderWidget::RequestPresentationAfterScrollAnimationEnd( + PresentationTimeCallback callback) { + layer_tree_host_->RequestScrollAnimationEndNotification( + base::BindOnce(&RenderWidget::RequestPresentation, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } viz::FrameSinkId RenderWidget::GetFrameSinkIdAtPoint(const gfx::PointF& point, gfx::PointF* local_point) { - return input_handler_->GetFrameSinkIdAtPoint(point, local_point); + blink::WebHitTestResult result = GetHitTestResultAtPoint(point); + + blink::WebNode result_node = result.GetNode(); + *local_point = gfx::PointF(point); + + // TODO(crbug.com/797828): When the node is null the caller may + // need to do extra checks. Like maybe update the layout and then + // call the hit-testing API. Either way it might be better to have + // a DCHECK for the node rather than a null check here. + if (result_node.IsNull()) { + return GetFrameSinkId(); + } + + viz::FrameSinkId frame_sink_id = GetRemoteFrameSinkId(result); + if (frame_sink_id.is_valid()) { + *local_point = gfx::PointF(result.LocalPointWithoutContentBoxOffset()); + if (compositor_deps()->IsUseZoomForDSFEnabled()) { + *local_point = gfx::ConvertPointToDIP( + GetOriginalScreenInfo().device_scale_factor, *local_point); + } + return frame_sink_id; + } + + // Return the FrameSinkId for the current widget if the point did not hit + // test to a remote frame, or the point is outside of the remote frame's + // content box, or the remote frame doesn't have a valid FrameSinkId yet. + return GetFrameSinkId(); } bool RenderWidget::HandleInputEvent( const blink::WebCoalescedInputEvent& input_event, HandledEventCallback callback) { - input_handler_->HandleInputEvent(input_event, std::move(callback)); + // Temporarily convert between the blink callback and the main thread + // event queue callback. This will go away once the MainThreadEventQueue + // moves into blink. + WebWidget::HandledEventCallback blink_callback = base::BindOnce( + [](HandledEventCallback callback, + blink::mojom::InputEventResultState ack_state, + const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams> + overscroll_params, + base::Optional<cc::TouchAction> touch_action) { + if (!callback) + return; + std::move(callback).Run(ack_state, latency_info, + ToOverscrollParams(overscroll_params.get()), + touch_action); + }, + std::move(callback)); + webwidget_->ProcessInputEventSynchronously(input_event, + std::move(blink_callback)); return true; } @@ -1074,7 +1108,13 @@ void RenderWidget::OnMouseCaptureLost() { void RenderWidget::OnSetEditCommandsForNextKeyEvent( std::vector<blink::mojom::EditCommandPtr> edit_commands) { - edit_commands_ = std::move(edit_commands); + if (auto* frame_widget = GetFrameWidget()) { + for (auto& command : edit_commands) { + frame_widget->AddEditCommandForNextKeyEvent( + WebString::FromUTF8(command->name), + WebString::FromUTF8(command->value)); + } + } } void RenderWidget::OnSetActive(bool active) { @@ -1083,13 +1123,13 @@ void RenderWidget::OnSetActive(bool active) { } void RenderWidget::OnSetFocus(bool enable) { + GetWebWidget()->SetFocus(enable); +} + +void RenderWidget::FocusChanged(bool enable) { if (delegate()) delegate()->DidReceiveSetFocusEventForWidget(); - has_focus_ = enable; - - GetWebWidget()->SetFocus(enable); - for (auto& observer : render_frames_) observer.RenderWidgetSetFocus(enable); } @@ -1185,32 +1225,7 @@ void RenderWidget::RecordTimeToFirstActivePaint(base::TimeDelta duration) { } } -void RenderWidget::WillBeginMainFrame() { - TRACE_EVENT0("gpu", "RenderWidget::willBeginCompositorFrame"); - - // The UpdateTextInputState can result in further layout and possibly - // enable GPU acceleration so they need to be called before any painting - // is done. - UpdateTextInputState(); - UpdateSelectionBounds(); -} - -/////////////////////////////////////////////////////////////////////////////// -// RenderWidgetInputHandlerDelegate - -void RenderWidget::FocusChangeComplete() { - blink::WebFrameWidget* frame_widget = GetFrameWidget(); - if (!frame_widget) - return; - - blink::WebLocalFrame* focused = - frame_widget->LocalRoot()->View()->FocusedFrame(); - - if (focused && focused->AutofillClient()) - focused->AutofillClient()->DidCompleteFocusChangeInFrame(); -} - -void RenderWidget::ObserveGestureEventAndResult( +void RenderWidget::DidHandleGestureScrollEvent( const blink::WebGestureEvent& gesture_event, const gfx::Vector2dF& unused_delta, const cc::OverscrollBehavior& overscroll_behavior, @@ -1228,160 +1243,96 @@ void RenderWidget::ObserveGestureEventAndResult( scroll_result); } -void RenderWidget::OnDidHandleKeyEvent() { - ClearEditCommands(); +void RenderWidget::DidOverscroll(const gfx::Vector2dF& overscroll_delta, + const gfx::Vector2dF& accumulated_overscroll, + const gfx::PointF& position_in_viewport, + const gfx::Vector2dF& velocity_in_viewport, + cc::OverscrollBehavior overscroll_behavior) { + if (blink::mojom::WidgetInputHandlerHost* host = + widget_input_handler_manager_->GetWidgetInputHandlerHost()) { + host->DidOverscroll(blink::mojom::DidOverscrollParams::New( + accumulated_overscroll, overscroll_delta, velocity_in_viewport, + position_in_viewport, overscroll_behavior)); + } } -void RenderWidget::SetEditCommandForNextKeyEvent(const std::string& name, - const std::string& value) { - ClearEditCommands(); - edit_commands_.push_back(blink::mojom::EditCommand::New(name, value)); +void RenderWidget::QueueSyntheticEvent( + std::unique_ptr<blink::WebCoalescedInputEvent> event) { + // TODO(acomminos): If/when we add support for gesture event attribution on + // the impl thread, have the caller provide attribution. + blink::WebInputEventAttribution attribution; + GetInputEventQueue()->HandleEvent( + std::move(event), DISPATCH_TYPE_NON_BLOCKING, + blink::mojom::InputEventResultState::kNotConsumed, attribution, + HandledEventCallback()); } -void RenderWidget::ClearEditCommands() { - edit_commands_.clear(); +void RenderWidget::GetWidgetInputHandler( + blink::CrossVariantMojoReceiver< + blink::mojom::WidgetInputHandlerInterfaceBase> widget_input_receiver, + blink::CrossVariantMojoRemote< + blink::mojom::WidgetInputHandlerHostInterfaceBase> + widget_input_host_remote) { + widget_input_handler_manager_->AddInterface( + std::move(widget_input_receiver), std::move(widget_input_host_remote)); } -void RenderWidget::OnDidOverscroll( - blink::mojom::DidOverscrollParamsPtr params) { - if (mojom::WidgetInputHandlerHost* host = - widget_input_handler_manager_->GetWidgetInputHandlerHost()) { - host->DidOverscroll(std::move(params)); - } +bool RenderWidget::HasCurrentImeGuard(bool request_to_show_virtual_keyboard) { + if (!ime_event_guard_) + return false; + if (request_to_show_virtual_keyboard) + ime_event_guard_->set_show_virtual_keyboard(true); + return true; } -void RenderWidget::SetInputHandler(RenderWidgetInputHandler* input_handler) { - // Nothing to do here. RenderWidget created the |input_handler| and will take - // ownership of it. We just verify here that we don't already have an input - // handler. - DCHECK(!input_handler_); +void RenderWidget::SendCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds) { + if (blink::mojom::WidgetInputHandlerHost* host = + widget_input_handler_manager_->GetWidgetInputHandlerHost()) { + host->ImeCompositionRangeChanged(range, character_bounds); + } } -void RenderWidget::ShowVirtualKeyboard() { - UpdateTextInputStateInternal(true, false); +bool RenderWidget::CanComposeInline() { +#if BUILDFLAG(ENABLE_PLUGINS) + if (auto* plugin = GetFocusedPepperPluginInsideWidget()) + return plugin->IsPluginAcceptingCompositionEvents(); +#endif + return true; } -void RenderWidget::ClearTextInputState() { - text_input_info_ = blink::WebTextInputInfo(); - text_input_type_ = ui::TextInputType::TEXT_INPUT_TYPE_NONE; - text_input_mode_ = ui::TextInputMode::TEXT_INPUT_MODE_DEFAULT; - can_compose_inline_ = false; - text_input_flags_ = 0; - next_previous_flags_ = kInvalidNextPreviousFlagsValue; +bool RenderWidget::ShouldDispatchImeEventsToPepper() { +#if BUILDFLAG(ENABLE_PLUGINS) + return GetFocusedPepperPluginInsideWidget(); +#else + return false; +#endif } -void RenderWidget::UpdateTextInputState() { - UpdateTextInputStateInternal(false, false); +blink::WebTextInputType RenderWidget::GetPepperTextInputType() { +#if BUILDFLAG(ENABLE_PLUGINS) + return ConvertTextInputType( + GetFocusedPepperPluginInsideWidget()->text_input_type()); +#else + NOTREACHED(); + return blink::WebTextInputType::kWebTextInputTypeNone; +#endif } -void RenderWidget::UpdateTextInputStateInternal(bool show_virtual_keyboard, - bool reply_to_request) { - TRACE_EVENT0("renderer", "RenderWidget::UpdateTextInputState"); - - if (ime_event_guard_) { - DCHECK(!reply_to_request); - // show_virtual_keyboard should still be effective even if it was set inside - // the IME - // event guard. - if (show_virtual_keyboard) - ime_event_guard_->set_show_virtual_keyboard(true); - return; - } - - ui::TextInputType new_type = GetTextInputType(); - if (IsDateTimeInput(new_type)) - return; // Not considered as a text input field in WebKit/Chromium. - - blink::WebTextInputInfo new_info; - if (auto* controller = GetInputMethodController()) { - new_info = controller->TextInputInfo(); - // Check if the input panel policy in |EditContext| is set to manual or not. - // This will be used to decide whether or not to show VK when |EditContext| - // is set focus. - if (controller->IsEditContextActive()) - show_virtual_keyboard = !controller->IsInputPanelPolicyManual(); - } - const ui::TextInputMode new_mode = - ConvertWebTextInputMode(new_info.input_mode); - - bool new_can_compose_inline = CanComposeInline(); - - // Check whether the keyboard should always be hidden for the currently - // focused element. - auto* focused_frame = GetFocusedWebLocalFrameInWidget(); - bool always_hide_ime = - focused_frame && focused_frame->ShouldSuppressKeyboardForFocusedElement(); - - // Only sends text input params if they are changed or if the ime should be - // shown. - if (show_virtual_keyboard || reply_to_request || - text_input_type_ != new_type || text_input_mode_ != new_mode || - text_input_info_ != new_info || - can_compose_inline_ != new_can_compose_inline || - always_hide_ime_ != always_hide_ime) { - TextInputState params; - params.type = new_type; - params.mode = new_mode; - params.action = new_info.action; - params.flags = new_info.flags; - if (auto* controller = GetInputMethodController()) { - WebRect control_bounds; - WebRect selection_bounds; - controller->GetLayoutBounds(&control_bounds, &selection_bounds); - ConvertViewportToWindow(&control_bounds); - params.edit_context_control_bounds = control_bounds; - if (controller->IsEditContextActive()) { - ConvertViewportToWindow(&selection_bounds); - params.edit_context_selection_bounds = selection_bounds; - } - } -#if defined(OS_ANDROID) - if (next_previous_flags_ == kInvalidNextPreviousFlagsValue) { - // Due to a focus change, values will be reset by the frame. - // That case we only need fresh NEXT/PREVIOUS information. - // Also we won't send WidgetHostMsg_TextInputStateChanged if next/previous - // focusable status is changed. - if (auto* controller = GetInputMethodController()) { - next_previous_flags_ = - controller->ComputeWebTextInputNextPreviousFlags(); - } else { - // For safety in case GetInputMethodController() is null, because -1 is - // invalid value to send to browser process. - next_previous_flags_ = 0; - } - } +gfx::Rect RenderWidget::GetPepperCaretBounds() { +#if BUILDFLAG(ENABLE_PLUGINS) + blink::WebRect caret(GetFocusedPepperPluginInsideWidget()->GetCaretBounds()); + ConvertViewportToWindow(&caret); + return caret; #else - next_previous_flags_ = 0; + NOTREACHED(); + return gfx::Rect(); #endif - params.flags |= next_previous_flags_; - params.value = new_info.value.Utf16(); - params.selection_start = new_info.selection_start; - params.selection_end = new_info.selection_end; - params.composition_start = new_info.composition_start; - params.composition_end = new_info.composition_end; - params.can_compose_inline = new_can_compose_inline; - // TODO(changwan): change instances of show_ime_if_needed to - // show_virtual_keyboard. - params.show_ime_if_needed = show_virtual_keyboard; - params.always_hide_ime = always_hide_ime; - params.reply_to_request = reply_to_request; - Send(new WidgetHostMsg_TextInputStateChanged(routing_id(), params)); - - text_input_info_ = new_info; - text_input_type_ = new_type; - text_input_mode_ = new_mode; - can_compose_inline_ = new_can_compose_inline; - always_hide_ime_ = always_hide_ime; - text_input_flags_ = new_info.flags; +} -#if defined(OS_ANDROID) - // If we send a new TextInputStateChanged message, we must also deliver a - // new RenderFrameMetadata, as the IME will need this info to be updated. - // TODO(ericrk): Consider folding the above IPC into RenderFrameMetadata. - // https://crbug.com/912309 - layer_tree_host_->RequestForceSendMetadata(); -#endif - } +void RenderWidget::UpdateTextInputState() { + GetWebWidget()->UpdateTextInputState(); } bool RenderWidget::WillHandleGestureEvent(const blink::WebGestureEvent& event) { @@ -1405,11 +1356,6 @@ bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) { return mouse_lock_dispatcher()->WillHandleMouseEvent(event); } -bool RenderWidget::SupportsBufferedTouchEvents() { - // Buffered touch events aren't supported for pepper. - return !pepper_fullscreen_; -} - void RenderWidget::ResizeWebWidget() { // In auto resize mode, blink controls sizes and RenderWidget should not be // passing values back in. @@ -1518,11 +1464,6 @@ void RenderWidget::SetScreenRects(const gfx::Rect& widget_screen_rect, // WebWidgetClient void RenderWidget::DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) { - if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) { - QueueMessage(std::make_unique<WidgetHostMsg_DidFirstVisuallyNonEmptyPaint>( - routing_id_)); - } - for (auto& observer : render_frames_) observer.DidMeaningfulLayout(layout_type); } @@ -1543,7 +1484,7 @@ std::unique_ptr<cc::SwapPromise> RenderWidget::QueueMessageImpl( } void RenderWidget::SetHandlingInputEvent(bool handling_input_event) { - input_handler_->set_handling_input_event(handling_input_event); + GetWebWidget()->SetHandlingInputEvent(handling_input_event); } void RenderWidget::QueueMessage(std::unique_ptr<IPC::Message> msg) { @@ -1559,13 +1500,14 @@ void RenderWidget::QueueMessage(std::unique_ptr<IPC::Message> msg) { layer_tree_host_->SourceFrameNumber()); if (swap_promise) { layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); - } -} -void RenderWidget::DidChangeCursor(const ui::Cursor& cursor) { - // Only send a SetCursor message if we need to make a change. - if (input_handler_->DidChangeCursor(cursor)) - GetWebWidget()->SetCursor(cursor); + // Request a main frame if one is not already in progress. This might either + // A) request a commit ahead of time or B) request a commit which is not + // needed because there are not pending updates. If B) then the frame will + // be aborted early and the swap promises will be broken (see + // EarlyOut_NoUpdates). + layer_tree_host_->SetNeedsAnimateIfNotInsideMainFrame(); + } } // We are supposed to get a single call to Show for a newly created RenderWidget @@ -1640,7 +1582,7 @@ void RenderWidget::InitCompositing(const ScreenInfo& screen_info) { main_thread_scheduler, uses_input_handler); const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kAllowPreCommitInput)) + if (command_line.HasSwitch(blink::switches::kAllowPreCommitInput)) widget_input_handler_manager_->AllowPreCommitInput(); } @@ -1688,7 +1630,6 @@ void RenderWidget::Close(std::unique_ptr<RenderWidget> widget) { // Browser correspondence is no longer needed at this point. if (routing_id_ != MSG_ROUTING_NONE) { RenderThread::Get()->RemoveRoute(routing_id_); - g_routing_id_widget_map.Get().erase(routing_id_); } // The |input_event_queue_| is refcounted and will live while an event is @@ -1824,11 +1765,6 @@ WebRect RenderWidget::ViewRect() { return rect; } -void RenderWidget::SetToolTipText(const blink::WebString& text, - base::i18n::TextDirection hint) { - Send(new WidgetHostMsg_SetTooltipText(routing_id_, text.Utf16(), hint)); -} - void RenderWidget::SetWindowRect(const WebRect& rect_in_screen) { // This path is for the renderer to change the on-screen position/size of // the widget by changing its window rect. This is not possible for @@ -1889,7 +1825,7 @@ void RenderWidget::OnShowContextMenu(ui::MenuSourceType source_type, void RenderWidget::OnImeSetComposition( const base::string16& text, - const std::vector<WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int selection_start, int selection_end) { @@ -1907,7 +1843,8 @@ void RenderWidget::OnImeSetComposition( blink::WebInputMethodController* controller = GetInputMethodController(); if (!controller || !controller->SetComposition( - WebString::FromUTF16(text), WebVector<WebImeTextSpan>(ime_text_spans), + WebString::FromUTF16(text), + WebVector<ui::ImeTextSpan>(ime_text_spans), replacement_range.IsValid() ? WebRange(replacement_range.start(), replacement_range.length()) : WebRange(), @@ -1915,17 +1852,17 @@ void RenderWidget::OnImeSetComposition( // If we failed to set the composition text, then we need to let the browser // process to cancel the input method's ongoing composition session, to make // sure we are in a consistent state. - if (mojom::WidgetInputHandlerHost* host = + if (blink::mojom::WidgetInputHandlerHost* host = widget_input_handler_manager_->GetWidgetInputHandlerHost()) { host->ImeCancelComposition(); } } - UpdateCompositionInfo(false /* not an immediate request */); + UpdateCompositionInfo(); } void RenderWidget::OnImeCommitText( const base::string16& text, - const std::vector<WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos) { if (!ShouldHandleImeEvents()) @@ -1939,17 +1876,17 @@ void RenderWidget::OnImeCommitText( } #endif ImeEventGuard guard(weak_ptr_factory_.GetWeakPtr()); - input_handler_->set_handling_input_event(true); + GetWebWidget()->SetHandlingInputEvent(true); if (auto* controller = GetInputMethodController()) { controller->CommitText( - WebString::FromUTF16(text), WebVector<WebImeTextSpan>(ime_text_spans), + WebString::FromUTF16(text), WebVector<ui::ImeTextSpan>(ime_text_spans), replacement_range.IsValid() ? WebRange(replacement_range.start(), replacement_range.length()) : WebRange(), relative_cursor_pos); } - input_handler_->set_handling_input_event(false); - UpdateCompositionInfo(false /* not an immediate request */); + GetWebWidget()->SetHandlingInputEvent(false); + UpdateCompositionInfo(); } void RenderWidget::OnImeFinishComposingText(bool keep_selection) { @@ -1964,14 +1901,23 @@ void RenderWidget::OnImeFinishComposingText(bool keep_selection) { #endif ImeEventGuard guard(weak_ptr_factory_.GetWeakPtr()); - input_handler_->set_handling_input_event(true); + GetWebWidget()->SetHandlingInputEvent(true); if (auto* controller = GetInputMethodController()) { controller->FinishComposingText( keep_selection ? WebInputMethodController::kKeepSelection : WebInputMethodController::kDoNotKeepSelection); } - input_handler_->set_handling_input_event(false); - UpdateCompositionInfo(false /* not an immediate request */); + GetWebWidget()->SetHandlingInputEvent(false); + UpdateCompositionInfo(); +} + +void RenderWidget::OnRequestTextInputStateUpdate() { + GetWebWidget()->ForceTextInputStateUpdate(); +} + +void RenderWidget::OnRequestCompositionUpdates(bool immediate_request, + bool monitor_updates) { + GetWebWidget()->RequestCompositionUpdates(immediate_request, monitor_updates); } void RenderWidget::UpdateSurfaceAndScreenInfo( @@ -2066,11 +2012,6 @@ void RenderWidget::SetWindowRectSynchronously( } } -void RenderWidget::OnSetTextDirection(base::i18n::TextDirection direction) { - if (auto* frame = GetFocusedWebLocalFrameInWidget()) - frame->SetTextDirection(direction); -} - void RenderWidget::OnUpdateScreenRects(const gfx::Rect& widget_screen_rect, const gfx::Rect& window_screen_rect) { if (device_emulator_) { @@ -2108,32 +2049,6 @@ void RenderWidget::OnDragTargetDragEnter( Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation)); } -void RenderWidget::OnDragTargetDragOver(const gfx::PointF& client_point, - const gfx::PointF& screen_point, - WebDragOperationsMask ops, - int key_modifiers) { - blink::WebFrameWidget* frame_widget = GetFrameWidget(); - if (!frame_widget) - return; - - WebDragOperation operation = frame_widget->DragTargetDragOver( - ConvertWindowPointToViewport(client_point), screen_point, ops, - key_modifiers); - - Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation)); -} - -void RenderWidget::OnDragTargetDragLeave(const gfx::PointF& client_point, - const gfx::PointF& screen_point) { - blink::WebFrameWidget* frame_widget = GetFrameWidget(); - if (!frame_widget) - return; - - frame_widget - ->DragTargetDragLeave(ConvertWindowPointToViewport(client_point), - screen_point); -} - void RenderWidget::OnDragTargetDrop(const DropData& drop_data, const gfx::PointF& client_point, const gfx::PointF& screen_point, @@ -2147,73 +2062,6 @@ void RenderWidget::OnDragTargetDrop(const DropData& drop_data, screen_point, key_modifiers); } -void RenderWidget::OnDragSourceEnded(const gfx::PointF& client_point, - const gfx::PointF& screen_point, - WebDragOperation op) { - blink::WebFrameWidget* frame_widget = GetFrameWidget(); - if (!frame_widget) - return; - - frame_widget->DragSourceEndedAt(ConvertWindowPointToViewport(client_point), - screen_point, op); -} - -void RenderWidget::ShowVirtualKeyboardOnElementFocus() { -#if defined(OS_CHROMEOS) - // On ChromeOS, virtual keyboard is triggered only when users leave the - // mouse button or the finger and a text input element is focused at that - // time. Focus event itself shouldn't trigger virtual keyboard. - UpdateTextInputState(); -#else - ShowVirtualKeyboard(); -#endif - -// TODO(rouslan): Fix ChromeOS and Windows 8 behavior of autofill popup with -// virtual keyboard. -#if !defined(OS_ANDROID) - FocusChangeComplete(); -#endif -} - -ui::TextInputType RenderWidget::GetTextInputType() { -#if BUILDFLAG(ENABLE_PLUGINS) - if (auto* plugin = GetFocusedPepperPluginInsideWidget()) - return plugin->text_input_type(); -#endif - if (auto* controller = GetInputMethodController()) - return ConvertWebTextInputType(controller->TextInputType()); - return ui::TEXT_INPUT_TYPE_NONE; -} - -void RenderWidget::UpdateCompositionInfo(bool immediate_request) { - if (!monitor_composition_info_ && !immediate_request) - return; // Do not calculate composition info if not requested. - - TRACE_EVENT0("renderer", "RenderWidget::UpdateCompositionInfo"); - gfx::Range range; - std::vector<gfx::Rect> character_bounds; - - if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { - // Composition information is only available on editable node. - range = gfx::Range::InvalidRange(); - } else { - GetCompositionRange(&range); - GetCompositionCharacterBounds(&character_bounds); - } - - if (!immediate_request && - !ShouldUpdateCompositionInfo(range, character_bounds)) { - return; - } - composition_character_bounds_ = character_bounds; - composition_range_ = range; - if (mojom::WidgetInputHandlerHost* host = - widget_input_handler_manager_->GetWidgetInputHandlerHost()) { - host->ImeCompositionRangeChanged(composition_range_, - composition_character_bounds_); - } -} - void RenderWidget::ConvertViewportToWindow(blink::WebRect* rect) { if (compositor_deps_->IsUseZoomForDSFEnabled()) { float reverse = 1 / GetOriginalScreenInfo().device_scale_factor; @@ -2245,22 +2093,6 @@ void RenderWidget::ConvertWindowToViewport(blink::WebFloatRect* rect) { } } -void RenderWidget::OnRequestTextInputStateUpdate() { -#if defined(OS_ANDROID) - DCHECK(!ime_event_guard_); - UpdateSelectionBounds(); - UpdateTextInputStateInternal(false, true /* reply_to_request */); -#endif -} - -void RenderWidget::OnRequestCompositionUpdates(bool immediate_request, - bool monitor_updates) { - monitor_composition_info_ = monitor_updates; - if (!immediate_request) - return; - UpdateCompositionInfo(true /* immediate request */); -} - void RenderWidget::OnOrientationChange() { if (auto* frame_widget = GetFrameWidget()) { // LocalRoot() might return null for provisional main frames. In this case, @@ -2314,71 +2146,18 @@ void RenderWidget::OnImeEventGuardFinish(ImeEventGuard* guard) { UpdateSelectionBounds(); #if defined(OS_ANDROID) if (guard->show_virtual_keyboard()) - ShowVirtualKeyboard(); + GetWebWidget()->ShowVirtualKeyboard(); else UpdateTextInputState(); #endif } -void RenderWidget::GetSelectionBounds(gfx::Rect* focus, gfx::Rect* anchor) { -#if BUILDFLAG(ENABLE_PLUGINS) - if (auto* plugin = GetFocusedPepperPluginInsideWidget()) { - // TODO(kinaba) http://crbug.com/101101 - // Current Pepper IME API does not handle selection bounds. So we simply - // use the caret position as an empty range for now. It will be updated - // after Pepper API equips features related to surrounding text retrieval. - blink::WebRect caret(plugin->GetCaretBounds()); - ConvertViewportToWindow(&caret); - *focus = caret; - *anchor = caret; - return; - } -#endif - WebRect focus_webrect; - WebRect anchor_webrect; - GetWebWidget()->SelectionBounds(focus_webrect, anchor_webrect); - ConvertViewportToWindow(&focus_webrect); - ConvertViewportToWindow(&anchor_webrect); - *focus = focus_webrect; - *anchor = anchor_webrect; -} - void RenderWidget::UpdateSelectionBounds() { - TRACE_EVENT0("renderer", "RenderWidget::UpdateSelectionBounds"); - if (ime_event_guard_) - return; - -#if defined(USE_AURA) - // TODO(mohsen): For now, always send explicit selection IPC notifications for - // Aura beucause composited selection updates are not working for webview tags - // which regresses IME inside webview. Remove this when composited selection - // updates are fixed for webviews. See, http://crbug.com/510568. - bool send_ipc = true; -#else - // With composited selection updates, the selection bounds will be reported - // directly by the compositor, in which case explicit IPC selection - // notifications should be suppressed. - bool send_ipc = - !blink::WebRuntimeFeatures::IsCompositedSelectionUpdateEnabled(); -#endif - if (send_ipc) { - WidgetHostMsg_SelectionBounds_Params params; - params.is_anchor_first = false; - GetSelectionBounds(¶ms.anchor_rect, ¶ms.focus_rect); - if (selection_anchor_rect_ != params.anchor_rect || - selection_focus_rect_ != params.focus_rect) { - selection_anchor_rect_ = params.anchor_rect; - selection_focus_rect_ = params.focus_rect; - if (auto* focused_frame = GetFocusedWebLocalFrameInWidget()) { - focused_frame->SelectionTextDirection(params.focus_dir, - params.anchor_dir); - params.is_anchor_first = focused_frame->IsSelectionAnchorFirst(); - } - Send(new WidgetHostMsg_SelectionBoundsChanged(routing_id_, params)); - } - } + GetWebWidget()->UpdateSelectionBounds(); +} - UpdateCompositionInfo(false /* not an immediate request */); +void RenderWidget::UpdateCompositionInfo() { + GetWebWidget()->UpdateCompositionInfo(); } void RenderWidget::DidAutoResize(const gfx::Size& new_size) { @@ -2408,115 +2187,6 @@ void RenderWidget::DidAutoResize(const gfx::Size& new_size) { } } -void RenderWidget::GetCompositionCharacterBounds( - std::vector<gfx::Rect>* bounds) { - DCHECK(bounds); - bounds->clear(); - -#if BUILDFLAG(ENABLE_PLUGINS) - if (GetFocusedPepperPluginInsideWidget()) - return; -#endif - - blink::WebInputMethodController* controller = GetInputMethodController(); - if (!controller) - return; - blink::WebVector<blink::WebRect> bounds_from_blink; - if (!controller->GetCompositionCharacterBounds(bounds_from_blink)) - return; - - for (size_t i = 0; i < bounds_from_blink.size(); ++i) { - ConvertViewportToWindow(&bounds_from_blink[i]); - bounds->push_back(bounds_from_blink[i]); - } -} - -void RenderWidget::GetCompositionRange(gfx::Range* range) { -#if BUILDFLAG(ENABLE_PLUGINS) - if (GetFocusedPepperPluginInsideWidget()) - return; -#endif - blink::WebInputMethodController* controller = GetInputMethodController(); - WebRange web_range = controller ? controller->CompositionRange() : WebRange(); - if (web_range.IsNull()) { - *range = gfx::Range::InvalidRange(); - return; - } - range->set_start(web_range.StartOffset()); - range->set_end(web_range.EndOffset()); -} - -bool RenderWidget::ShouldUpdateCompositionInfo( - const gfx::Range& range, - const std::vector<gfx::Rect>& bounds) { - if (!range.IsValid()) - return false; - if (composition_range_ != range) - return true; - if (bounds.size() != composition_character_bounds_.size()) - return true; - for (size_t i = 0; i < bounds.size(); ++i) { - if (bounds[i] != composition_character_bounds_[i]) - return true; - } - return false; -} - -bool RenderWidget::CanComposeInline() { -#if BUILDFLAG(ENABLE_PLUGINS) - if (auto* plugin = GetFocusedPepperPluginInsideWidget()) - return plugin->IsPluginAcceptingCompositionEvents(); -#endif - return true; -} - -void RenderWidget::DidHandleGestureEvent(const WebGestureEvent& event, - bool event_cancelled) { - if (event_cancelled) { - // The delegate() doesn't need to hear about cancelled events. - return; - } - -#if defined(OS_ANDROID) || defined(USE_AURA) - if (event.GetType() == WebInputEvent::Type::kGestureTap) { - ShowVirtualKeyboard(); - } else if (event.GetType() == WebInputEvent::Type::kGestureLongPress) { - DCHECK(GetWebWidget()); - blink::WebInputMethodController* controller = GetInputMethodController(); - if (!controller || controller->TextInputInfo().value.IsEmpty()) - UpdateTextInputState(); - else - ShowVirtualKeyboard(); - } -#endif -} - -void RenderWidget::DidOverscroll(const gfx::Vector2dF& overscroll_delta, - const gfx::Vector2dF& accumulated_overscroll, - const gfx::PointF& position, - const gfx::Vector2dF& velocity) { -#if defined(OS_MACOSX) - // On OSX the user can disable the elastic overscroll effect. If that's the - // case, don't forward the overscroll notification. - DCHECK(compositor_deps()); - if (!compositor_deps()->IsElasticOverscrollEnabled()) - return; -#endif - input_handler_->DidOverscrollFromBlink( - overscroll_delta, accumulated_overscroll, position, velocity, - layer_tree_host_->overscroll_behavior()); -} - -void RenderWidget::InjectGestureScrollEvent( - blink::WebGestureDevice device, - const gfx::Vector2dF& delta, - ui::ScrollGranularity granularity, - cc::ElementId scrollable_area_element_id, - blink::WebInputEvent::Type injected_type) { - input_handler_->InjectGestureScrollEvent( - device, delta, granularity, scrollable_area_element_id, injected_type); -} - // static cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( CompositorDependencies* compositor_deps, @@ -2528,6 +2198,8 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( const base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess(); cc::LayerTreeSettings settings; + settings.enable_synchronized_scrolling = + base::FeatureList::IsEnabled(features::kSynchronizedScrolling); settings.use_zoom_for_dsf = compositor_deps->IsUseZoomForDSFEnabled(); settings.percent_based_scrolling = base::FeatureList::IsEnabled(features::kPercentBasedScrolling); @@ -2610,36 +2282,36 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( // TODO(danakj): This should not be a setting O_O; it should change when the // device scale factor on LayerTreeHost changes. settings.default_tile_size = gfx::Size(default_tile_size, default_tile_size); - if (cmd.HasSwitch(switches::kDefaultTileWidth)) { + if (cmd.HasSwitch(blink::switches::kDefaultTileWidth)) { int tile_width = 0; - switch_value_as_int(cmd, switches::kDefaultTileWidth, 1, + switch_value_as_int(cmd, blink::switches::kDefaultTileWidth, 1, std::numeric_limits<int>::max(), &tile_width); settings.default_tile_size.set_width(tile_width); } - if (cmd.HasSwitch(switches::kDefaultTileHeight)) { + if (cmd.HasSwitch(blink::switches::kDefaultTileHeight)) { int tile_height = 0; - switch_value_as_int(cmd, switches::kDefaultTileHeight, 1, + switch_value_as_int(cmd, blink::switches::kDefaultTileHeight, 1, std::numeric_limits<int>::max(), &tile_height); settings.default_tile_size.set_height(tile_height); } - if (cmd.HasSwitch(switches::kMinHeightForGpuRasterTile)) { + if (cmd.HasSwitch(blink::switches::kMinHeightForGpuRasterTile)) { int min_height_for_gpu_raster_tile = 0; - switch_value_as_int(cmd, switches::kMinHeightForGpuRasterTile, 1, + switch_value_as_int(cmd, blink::switches::kMinHeightForGpuRasterTile, 1, std::numeric_limits<int>::max(), &min_height_for_gpu_raster_tile); settings.min_height_for_gpu_raster_tile = min_height_for_gpu_raster_tile; } int max_untiled_layer_width = settings.max_untiled_layer_size.width(); - if (cmd.HasSwitch(switches::kMaxUntiledLayerWidth)) { - switch_value_as_int(cmd, switches::kMaxUntiledLayerWidth, 1, + if (cmd.HasSwitch(blink::switches::kMaxUntiledLayerWidth)) { + switch_value_as_int(cmd, blink::switches::kMaxUntiledLayerWidth, 1, std::numeric_limits<int>::max(), &max_untiled_layer_width); } int max_untiled_layer_height = settings.max_untiled_layer_size.height(); - if (cmd.HasSwitch(switches::kMaxUntiledLayerHeight)) { - switch_value_as_int(cmd, switches::kMaxUntiledLayerHeight, 1, + if (cmd.HasSwitch(blink::switches::kMaxUntiledLayerHeight)) { + switch_value_as_int(cmd, blink::switches::kMaxUntiledLayerHeight, 1, std::numeric_limits<int>::max(), &max_untiled_layer_height); } @@ -2705,9 +2377,9 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( settings.initial_debug_state.show_layer_animation_bounds_rects = cmd.HasSwitch(cc::switches::kShowLayerAnimationBounds); settings.initial_debug_state.show_paint_rects = - cmd.HasSwitch(switches::kShowPaintRects); + cmd.HasSwitch(blink::switches::kShowPaintRects); settings.initial_debug_state.show_layout_shift_regions = - cmd.HasSwitch(switches::kShowLayoutShiftRegions); + cmd.HasSwitch(blink::switches::kShowLayoutShiftRegions); settings.initial_debug_state.show_property_changed_rects = cmd.HasSwitch(cc::switches::kShowPropertyChangedRects); settings.initial_debug_state.show_surface_damage_rects = @@ -2826,7 +2498,7 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( // - If we are not using vulkan, since some GPU drivers don't support // using RGBA4444 as color buffer. // TODO(penghuang): query supported formats from GPU process. - if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures) && + if (!cmd.HasSwitch(blink::switches::kDisableRGBA4444Textures) && base::SysInfo::AmountOfPhysicalMemoryMB() <= 512 && !using_synchronous_compositor && !base::FeatureList::IsEnabled(features::kVulkan)) { @@ -2845,13 +2517,13 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( } } - if (cmd.HasSwitch(switches::kEnableLowResTiling)) + if (cmd.HasSwitch(blink::switches::kEnableLowResTiling)) settings.create_low_res_tiling = true; - if (cmd.HasSwitch(switches::kDisableLowResTiling)) + if (cmd.HasSwitch(blink::switches::kDisableLowResTiling)) settings.create_low_res_tiling = false; - if (cmd.HasSwitch(switches::kEnableRGBA4444Textures) && - !cmd.HasSwitch(switches::kDisableRGBA4444Textures)) { + if (cmd.HasSwitch(blink::switches::kEnableRGBA4444Textures) && + !cmd.HasSwitch(blink::switches::kDisableRGBA4444Textures)) { settings.use_rgba_4444 = true; } @@ -2884,7 +2556,7 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( } settings.enable_image_animation_resync = - !cmd.HasSwitch(switches::kDisableImageAnimationResync); + !cmd.HasSwitch(blink::switches::kDisableImageAnimationResync); settings.send_compositor_frame_ack = false; @@ -2897,6 +2569,9 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( // Disable occlusion if de-jelly effect is enabled. settings.enable_occlusion &= !settings.allow_de_jelly_effect; + settings.enable_transform_interop = + base::FeatureList::IsEnabled(blink::features::kTransformInterop); + return settings; } @@ -3057,9 +2732,6 @@ void RenderWidget::RequestUnbufferedInputEvents() { } void RenderWidget::SetTouchAction(cc::TouchAction touch_action) { - if (!input_handler_->ProcessTouchAction(touch_action)) - return; - widget_input_handler_manager_->ProcessTouchAction(touch_action); } @@ -3075,6 +2747,7 @@ void RenderWidget::RegisterRenderFrameProxy(RenderFrameProxy* proxy) { proxy->OnScreenInfoChanged(GetOriginalScreenInfo()); proxy->OnZoomLevelChanged(zoom_level_); proxy->OnVisibleViewportSizeChanged(visible_viewport_size_); + proxy->OnRootWindowSegmentsChanged(root_widget_window_segments_); } void RenderWidget::UnregisterRenderFrameProxy(RenderFrameProxy* proxy) { @@ -3177,27 +2850,12 @@ blink::WebInputMethodController* RenderWidget::GetInputMethodController() return nullptr; } -void RenderWidget::SetupWidgetInputHandler( - mojo::PendingReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { - widget_input_handler_manager_->AddInterface(std::move(receiver), - std::move(host)); -} - -void RenderWidget::SetWidgetReceiver( - mojo::PendingReceiver<mojom::Widget> recevier) { - // Close the old receiver if there was one. - // A RenderWidgetHost should not need more than one channel. - widget_receiver_.reset(); - widget_receiver_.Bind(std::move(recevier)); -} - -mojom::WidgetInputHandlerHost* RenderWidget::GetInputHandlerHost() { +blink::mojom::WidgetInputHandlerHost* RenderWidget::GetInputHandlerHost() { return widget_input_handler_manager_->GetWidgetInputHandlerHost(); } void RenderWidget::SetMouseCapture(bool capture) { - if (mojom::WidgetInputHandlerHost* host = + if (blink::mojom::WidgetInputHandlerHost* host = widget_input_handler_manager_->GetWidgetInputHandlerHost()) { host->SetMouseCapture(capture); } @@ -3209,7 +2867,12 @@ void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) { blink::WebHitTestResult RenderWidget::GetHitTestResultAtPoint( const gfx::PointF& point) { - return input_handler_->GetHitTestResultAtPoint(point); + gfx::PointF point_in_pixel(point); + if (compositor_deps()->IsUseZoomForDSFEnabled()) { + point_in_pixel = gfx::ConvertPointToPixel( + GetOriginalScreenInfo().device_scale_factor, point_in_pixel); + } + return GetWebWidget()->HitTestResultAt(point_in_pixel); } void RenderWidget::SetDeviceScaleFactorForTesting(float factor) { diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h index a62c46d27fb..76b3184fee5 100644 --- a/chromium/content/renderer/render_widget.h +++ b/chromium/content/renderer/render_widget.h @@ -34,11 +34,9 @@ #include "content/common/content_export.h" #include "content/common/content_to_visible_time_reporter.h" #include "content/common/drag_event_source_info.h" -#include "content/common/widget.mojom.h" #include "content/public/common/drop_data.h" +#include "content/public/common/screen_info.h" #include "content/renderer/input/main_thread_event_queue.h" -#include "content/renderer/input/render_widget_input_handler.h" -#include "content/renderer/input/render_widget_input_handler_delegate.h" #include "content/renderer/mouse_lock_dispatcher.h" #include "content/renderer/render_widget_delegate.h" #include "content/renderer/render_widget_mouse_lock_dispatcher.h" @@ -55,10 +53,10 @@ #include "third_party/blink/public/platform/viewport_intersection_state.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_text_input_info.h" -#include "third_party/blink/public/web/web_ime_text_span.h" #include "third_party/blink/public/web/web_page_popup.h" #include "third_party/blink/public/web/web_widget.h" #include "third_party/blink/public/web/web_widget_client.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" #include "ui/base/ui_base_types.h" @@ -100,10 +98,6 @@ struct PresentationFeedback; class Range; } -namespace ui { -class Cursor; -} - namespace content { class CompositorDependencies; class FrameSwapMessageQueue; @@ -140,16 +134,13 @@ class CONTENT_EXPORT RenderWidget : public IPC::Listener, public IPC::Sender, public blink::WebPagePopupClient, // Is-a WebWidgetClient also. - public mojom::Widget, - public RenderWidgetInputHandlerDelegate, public RenderWidgetScreenMetricsEmulatorDelegate, public MainThreadEventQueueClient { public: RenderWidget(int32_t widget_routing_id, CompositorDependencies* compositor_deps, bool hidden, - bool never_composited, - mojo::PendingReceiver<mojom::Widget> widget_receiver); + bool never_composited); ~RenderWidget() override; @@ -166,12 +157,11 @@ class CONTENT_EXPORT RenderWidget // Convenience type for creation method taken by InstallCreateForFrameHook(). // The method signature matches the RenderWidget constructor. - using CreateRenderWidgetFunction = std::unique_ptr<RenderWidget> (*)( - int32_t routing_id, - CompositorDependencies*, - bool hidden, - bool never_composited, - mojo::PendingReceiver<mojom::Widget> widget_receiver); + using CreateRenderWidgetFunction = + std::unique_ptr<RenderWidget> (*)(int32_t routing_id, + CompositorDependencies*, + bool hidden, + bool never_composited); // Overrides the implementation of CreateForFrame() function below. Used by // web tests to return a partial fake of RenderWidget. static void InstallCreateForFrameHook( @@ -190,12 +180,10 @@ class CONTENT_EXPORT RenderWidget // A RenderWidget popup is owned by the browser process. The object will be // destroyed by the WidgetMsg_Close message. The object can request its own // destruction via ClosePopupWidgetSoon(). - static RenderWidget* CreateForPopup( - int32_t widget_routing_id, - CompositorDependencies* compositor_deps, - bool hidden, - bool never_composited, - mojo::PendingReceiver<mojom::Widget> widget_receiver); + static RenderWidget* CreateForPopup(int32_t widget_routing_id, + CompositorDependencies* compositor_deps, + bool hidden, + bool never_composited); // Initialize a new RenderWidget for a popup. The |show_callback| is called // when RenderWidget::Show() happens. The |opener_widget| is the local root @@ -232,9 +220,6 @@ class CONTENT_EXPORT RenderWidget RenderWidgetDelegate* delegate() const { return delegate_; } - // Returns the RenderWidget for the given routing ID. - static RenderWidget* FromRoutingID(int32_t routing_id); - // Closes a RenderWidget that was created by |CreateForFrame|. Ownership is // passed into this object to asynchronously delete itself. void CloseForFrame(std::unique_ptr<RenderWidget> widget); @@ -273,14 +258,6 @@ class CONTENT_EXPORT RenderWidget // destroyed RenderWidget. bool IsForProvisionalFrame() const; - // Manage edit commands to be used for the next keyboard event. - const std::vector<blink::mojom::EditCommandPtr>& edit_commands() const { - return edit_commands_; - } - void SetEditCommandForNextKeyEvent(const std::string& name, - const std::string& value); - void ClearEditCommands(); - // Functions to track out-of-process frames for special notifications. void RegisterRenderFrameProxy(RenderFrameProxy* proxy); void UnregisterRenderFrameProxy(RenderFrameProxy* proxy); @@ -296,24 +273,6 @@ class CONTENT_EXPORT RenderWidget // IPC::Sender bool Send(IPC::Message* msg) override; - // RenderWidgetInputHandlerDelegate - void FocusChangeComplete() override; - void ObserveGestureEventAndResult( - const blink::WebGestureEvent& gesture_event, - const gfx::Vector2dF& unused_delta, - const cc::OverscrollBehavior& overscroll_behavior, - bool event_processed) override; - - void OnDidHandleKeyEvent() override; - void OnDidOverscroll(blink::mojom::DidOverscrollParamsPtr params) override; - void SetInputHandler(RenderWidgetInputHandler* input_handler) override; - void ShowVirtualKeyboard() override; - void UpdateTextInputState() override; - void ClearTextInputState() override; - bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override; - bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override; - bool SupportsBufferedTouchEvents() override; - // RenderWidgetScreenMetricsEmulatorDelegate void SetScreenMetricsEmulationParameters( bool enabled, @@ -327,28 +286,12 @@ class CONTENT_EXPORT RenderWidget // blink::WebWidgetClient void ScheduleAnimation() override; void DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) override; - void DidChangeCursor(const ui::Cursor& cursor) override; void ClosePopupWidgetSoon() override; void Show(blink::WebNavigationPolicy) override; blink::WebScreenInfo GetScreenInfo() override; blink::WebRect WindowRect() override; blink::WebRect ViewRect() override; - void SetToolTipText(const blink::WebString& text, - base::i18n::TextDirection hint) override; void SetWindowRect(const blink::WebRect&) override; - void DidHandleGestureEvent(const blink::WebGestureEvent& event, - bool event_cancelled) override; - void DidOverscroll(const gfx::Vector2dF& overscroll_delta, - const gfx::Vector2dF& accumulated_overscroll, - const gfx::PointF& position, - const gfx::Vector2dF& velocity) override; - void InjectGestureScrollEvent( - blink::WebGestureDevice device, - const gfx::Vector2dF& delta, - ui::ScrollGranularity granularity, - cc::ElementId scrollable_area_element_id, - blink::WebInputEvent::Type injected_type) override; - void ShowVirtualKeyboardOnElementFocus() override; void ConvertViewportToWindow(blink::WebRect* rect) override; void ConvertViewportToWindow(blink::WebFloatRect* rect) override; void ConvertWindowToViewport(blink::WebFloatRect* rect) override; @@ -385,9 +328,37 @@ class CONTENT_EXPORT RenderWidget void DidCommitAndDrawCompositorFrame() override; void DidCommitCompositorFrame(base::TimeTicks commit_start_time) override; void DidCompletePageScaleAnimation() override; - void WillBeginMainFrame() override; void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) override; + void DidHandleGestureScrollEvent( + const blink::WebGestureEvent& gesture_event, + const gfx::Vector2dF& unused_delta, + const cc::OverscrollBehavior& overscroll_behavior, + bool event_processed) override; + void DidOverscroll(const gfx::Vector2dF& overscroll_delta, + const gfx::Vector2dF& accumulated_overscroll, + const gfx::PointF& position_in_viewport, + const gfx::Vector2dF& velocity_in_viewport, + cc::OverscrollBehavior overscroll_behavior) override; + bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override; + bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override; + void QueueSyntheticEvent( + std::unique_ptr<blink::WebCoalescedInputEvent>) override; + void GetWidgetInputHandler( + blink::CrossVariantMojoReceiver< + blink::mojom::WidgetInputHandlerInterfaceBase> widget_input_receiver, + blink::CrossVariantMojoRemote< + blink::mojom::WidgetInputHandlerHostInterfaceBase> + widget_input_host_remote) override; + bool HasCurrentImeGuard(bool request_to_show_virtual_keyboard) override; + void SendCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds) override; + bool CanComposeInline() override; + bool ShouldDispatchImeEventsToPepper() override; + blink::WebTextInputType GetPepperTextInputType() override; + gfx::Rect GetPepperCaretBounds() override; + void FocusChanged(bool enable) override; // Returns the scale being applied to the document in blink by the device // emulator. Returns 1 if there is no emulation active. Use this to position @@ -395,9 +366,7 @@ class CONTENT_EXPORT RenderWidget // position. float GetEmulatorScale() const override; - // Override point to obtain that the current input method state and caret - // position. - ui::TextInputType GetTextInputType(); + void UpdateTextInputState(); // Sends a request to the browser to close this RenderWidget. void CloseWidgetSoon(); @@ -416,10 +385,6 @@ class CONTENT_EXPORT RenderWidget WidgetInputHandlerManager* widget_input_handler_manager() { return widget_input_handler_manager_.get(); } - const RenderWidgetInputHandler& input_handler() const { - return *input_handler_; - } - void SetHandlingInputEvent(bool handling_input_event); // Queues the IPC |message| to be sent to the browser, delaying sending until @@ -449,23 +414,11 @@ class CONTENT_EXPORT RenderWidget // handle composition range and composition character bounds. // If immediate_request is true, render sends the latest composition info to // the browser even if the composition info is not changed. - void UpdateCompositionInfo(bool immediate_request); - - // Override point to obtain that the current composition character bounds. - // In the case of surrogate pairs, the character is treated as two characters: - // the bounds for first character is actual one, and the bounds for second - // character is zero width rectangle. - void GetCompositionCharacterBounds(std::vector<gfx::Rect>* character_bounds); + void UpdateCompositionInfo(); // Called when the Widget has changed size as a result of an auto-resize. void DidAutoResize(const gfx::Size& new_size); - void DidPresentForceDrawFrame(int snapshot_id, - const gfx::PresentationFeedback& feedback); - - // Indicates whether this widget has focus. - bool has_focus() const { return has_focus_; } - MouseLockDispatcher* mouse_lock_dispatcher() const { return mouse_lock_dispatcher_.get(); } @@ -500,12 +453,7 @@ class CONTENT_EXPORT RenderWidget viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point, gfx::PointF* local_point); - // Widget mojom overrides. - void SetupWidgetInputHandler( - mojo::PendingReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) override; - - mojom::WidgetInputHandlerHost* GetInputHandlerHost(); + blink::mojom::WidgetInputHandlerHost* GetInputHandlerHost(); scoped_refptr<MainThreadEventQueue> GetInputEventQueue(); @@ -515,14 +463,13 @@ class CONTENT_EXPORT RenderWidget void OnCursorVisibilityChange(bool is_visible); void OnSetEditCommandsForNextKeyEvent( std::vector<blink::mojom::EditCommandPtr> edit_commands); - void OnImeSetComposition( - const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, - const gfx::Range& replacement_range, - int selection_start, - int selection_end); + void OnImeSetComposition(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + const gfx::Range& replacement_range, + int selection_start, + int selection_end); void OnImeCommitText(const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos); void OnImeFinishComposingText(bool keep_selection); @@ -539,7 +486,6 @@ class CONTENT_EXPORT RenderWidget // composition info (when in monitor mode). void OnRequestCompositionUpdates(bool immediate_request, bool monitor_updates); - void SetWidgetReceiver(mojo::PendingReceiver<mojom::Widget> receiver); void SetMouseCapture(bool capture); @@ -557,13 +503,30 @@ class CONTENT_EXPORT RenderWidget blink::WebHitTestResult GetHitTestResultAtPoint(const gfx::PointF& point); // Forces a redraw and invokes the callback once the frame's been displayed - // to the user. + // to the user in the display compositor. using PresentationTimeCallback = base::OnceCallback<void(const gfx::PresentationFeedback&)>; virtual void RequestPresentation(PresentationTimeCallback callback); + // Forces a redraw after any ongoing scroll-animation ends, and invokes the + // callback once the frame is displayed to the user. + void RequestPresentationAfterScrollAnimationEnd( + PresentationTimeCallback callback); + base::WeakPtr<RenderWidget> AsWeakPtr(); + // This method returns the WebLocalFrame which is currently focused and + // belongs to the frame tree associated with this RenderWidget. + blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const; + + bool handling_select_range() const { return handling_select_range_; } + + bool is_pasting() const { return is_pasting_; } + + void set_is_pasting(bool value) { is_pasting_ = value; } + + void set_handling_select_range(bool value) { handling_select_range_ = value; } + protected: // Notify subclasses that we handled OnUpdateVisualProperties. virtual void AfterUpdateVisualProperties() {} @@ -637,11 +600,9 @@ class CONTENT_EXPORT RenderWidget void OnCreateVideoAck(int32_t video_id); void OnUpdateVideoAck(int32_t video_id); void OnRequestSetBoundsAck(); - void OnForceRedraw(int snapshot_id); void OnShowContextMenu(ui::MenuSourceType source_type, const gfx::Point& location); - void OnSetTextDirection(base::i18n::TextDirection direction); void OnGetFPS(); void OnUpdateScreenRects(const gfx::Rect& widget_screen_rect, const gfx::Rect& window_screen_rect); @@ -653,12 +614,6 @@ class CONTENT_EXPORT RenderWidget const gfx::PointF& screen_pt, blink::WebDragOperationsMask operations_allowed, int key_modifiers); - void OnDragTargetDragOver(const gfx::PointF& client_pt, - const gfx::PointF& screen_pt, - blink::WebDragOperationsMask operations_allowed, - int key_modifiers); - void OnDragTargetDragLeave(const gfx::PointF& client_point, - const gfx::PointF& screen_point); void OnDragTargetDrop(const DropData& drop_data, const gfx::PointF& client_pt, const gfx::PointF& screen_pt, @@ -687,20 +642,6 @@ class CONTENT_EXPORT RenderWidget scoped_refptr<IPC::SyncMessageFilter> sync_message_filter, int source_frame_number); - // Returns the range of the text that is being composed or the selection if - // the composition does not exist. - void GetCompositionRange(gfx::Range* range); - - // Returns true if the composition range or composition character bounds - // should be sent to the browser process. - bool ShouldUpdateCompositionInfo( - const gfx::Range& range, - const std::vector<gfx::Rect>& bounds); - - // Override point to obtain that the current input method state about - // composition text. - bool CanComposeInline(); - // Set the pending window rect. // Because the real render_widget is hosted in another process, there is // a time period where we may have set a new window rect which has not yet @@ -746,10 +687,6 @@ class CONTENT_EXPORT RenderWidget PepperPluginInstanceImpl* GetFocusedPepperPluginInsideWidget(); #endif - // This method returns the WebLocalFrame which is currently focused and - // belongs to the frame tree associated with this RenderWidget. - blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const; - // Whether this widget is for a frame. This excludes widgets that are not for // a frame (eg popups, pepper), but includes both the main frame // (via delegate_) and subframes (via for_child_local_root_frame_). @@ -859,38 +796,6 @@ class CONTENT_EXPORT RenderWidget // the browser if they disagree. bool synchronous_resize_mode_for_testing_ = false; - // Stores information about the current text input. - blink::WebTextInputInfo text_input_info_; - - // Stores the current text input type of |webwidget_|. - ui::TextInputType text_input_type_ = ui::TEXT_INPUT_TYPE_NONE; - - // Stores the current text input mode of |webwidget_|. - ui::TextInputMode text_input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT; - - // Stores the current text input flags of |webwidget_|. - int text_input_flags_ = 0; - - // Indicates whether currently focused input field has next/previous focusable - // form input field. - int next_previous_flags_; - - // Stores the current type of composition text rendering of |webwidget_|. - bool can_compose_inline_ = true; - - // Stores whether the IME should always be hidden for |webwidget_|. - bool always_hide_ime_ = false; - - // Stores the current selection bounds. - gfx::Rect selection_focus_rect_; - gfx::Rect selection_anchor_rect_; - - // Stores the current composition character bounds. - std::vector<gfx::Rect> composition_character_bounds_; - - // Stores the current composition range. - gfx::Range composition_range_ = gfx::Range::InvalidRange(); - // While we are waiting for the browser to update window sizes, we track the // pending size temporarily. int pending_window_rect_count_ = 0; @@ -906,16 +811,16 @@ class CONTENT_EXPORT RenderWidget gfx::Rect widget_screen_rect_; gfx::Rect window_screen_rect_; - scoped_refptr<WidgetInputHandlerManager> widget_input_handler_manager_; + // Stored during the SynchronizeVisualProperties cascade. See VisualProperties + // for a more detailed explanation of how when this value is computed and + // propagated. + std::vector<gfx::Rect> root_widget_window_segments_; - std::unique_ptr<RenderWidgetInputHandler> input_handler_; + scoped_refptr<WidgetInputHandlerManager> widget_input_handler_manager_; // The time spent in input handlers this frame. Used to throttle input acks. base::TimeDelta total_input_handling_time_this_frame_; - // True if the IME requests updated composition info. - bool monitor_composition_info_ = false; - scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_; // Lists of RenderFrameProxy objects for which this RenderWidget is their @@ -942,9 +847,6 @@ class CONTENT_EXPORT RenderWidget viz::LocalSurfaceIdAllocation local_surface_id_allocation_from_parent_; - // Indicates whether this widget has focus. - bool has_focus_ = false; - // Whether this widget is for a child local root frame. This excludes widgets // that are not for a frame (eg popups) and excludes the widget for the main // frame (which is attached to the RenderViewImpl). @@ -967,10 +869,6 @@ class CONTENT_EXPORT RenderWidget std::unique_ptr<TextInputClientObserver> text_input_client_observer_; #endif - // Stores edit commands associated to the next key event. - // Will be cleared as soon as the next key event is processed. - std::vector<blink::mojom::EditCommandPtr> edit_commands_; - // This field stores drag/drop related info for the event that is currently // being handled. If the current event results in starting a drag/drop // session, this info is sent to the browser along with other drag/drop info. @@ -990,13 +888,17 @@ class CONTENT_EXPORT RenderWidget bool is_pinch_gesture_active_from_mainframe_ = false; scoped_refptr<MainThreadEventQueue> input_event_queue_; - - mojo::Receiver<mojom::Widget> widget_receiver_; - gfx::Rect compositor_visible_rect_; uint32_t last_capture_sequence_number_ = 0u; + // Used to inform didChangeSelection() when it is called in the context + // of handling a FrameInputHandler::SelectRange IPC. + bool handling_select_range_ = false; + + // Whether or not this RenderWidget is currently pasting. + bool is_pasting_ = false; + std::unique_ptr<blink::scheduler::WebWidgetScheduler> widget_scheduler_; base::WeakPtrFactory<RenderWidget> weak_ptr_factory_{this}; diff --git a/chromium/content/renderer/render_widget_browsertest.cc b/chromium/content/renderer/render_widget_browsertest.cc index c4f7ecee747..6e43f93603d 100644 --- a/chromium/content/renderer/render_widget_browsertest.cc +++ b/chromium/content/renderer/render_widget_browsertest.cc @@ -8,6 +8,7 @@ #include "content/common/visual_properties.h" #include "content/common/widget_messages.h" #include "content/public/renderer/render_frame_visitor.h" +#include "content/public/test/fake_render_widget_host.h" #include "content/public/test/render_view_test.h" #include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_thread_impl.h" @@ -37,8 +38,11 @@ class RenderWidgetTest : public RenderViewTest { widget()->OnMessageReceived(msg); } - void GetCompositionRange(gfx::Range* range) { - widget()->GetCompositionRange(range); + gfx::Range LastCompositionRange() { + render_widget_host_->GetWidgetInputHandler()->RequestCompositionUpdates( + true, false); + base::RunLoop().RunUntilIdle(); + return render_widget_host_->LastCompositionRange(); } blink::WebInputMethodController* GetInputMethodController() { @@ -46,14 +50,13 @@ class RenderWidgetTest : public RenderViewTest { } void CommitText(std::string text) { - widget()->OnImeCommitText(base::UTF8ToUTF16(text), - std::vector<blink::WebImeTextSpan>(), - gfx::Range::InvalidRange(), 0); + render_widget_host_->GetWidgetInputHandler()->ImeCommitText( + base::UTF8ToUTF16(text), std::vector<ui::ImeTextSpan>(), + gfx::Range::InvalidRange(), 0, base::DoNothing()); + base::RunLoop().RunUntilIdle(); } - ui::TextInputType GetTextInputType() { return widget()->GetTextInputType(); } - - void SetFocus(bool focused) { widget()->OnSetFocus(focused); } + void SetFocus(bool focused) { GetWebWidget()->SetFocus(focused); } gfx::PointF GetCenterPointOfElement(const blink::WebString& id) { auto rect = @@ -288,12 +291,13 @@ TEST_F(RenderWidgetTest, GetCompositionRangeValidComposition) { LoadHTML( "<div contenteditable>EDITABLE</div>" "<script> document.querySelector('div').focus(); </script>"); - blink::WebVector<blink::WebImeTextSpan> empty_ime_text_spans; + gfx::Range range = LastCompositionRange(); + EXPECT_FALSE(range.IsValid()); + blink::WebVector<ui::ImeTextSpan> empty_ime_text_spans; DCHECK(widget()->GetInputMethodController()); widget()->GetInputMethodController()->SetComposition( "hello", empty_ime_text_spans, blink::WebRange(), 3, 3); - gfx::Range range; - GetCompositionRange(&range); + range = LastCompositionRange(); EXPECT_TRUE(range.IsValid()); EXPECT_EQ(0U, range.start()); EXPECT_EQ(5U, range.end()); @@ -303,16 +307,14 @@ TEST_F(RenderWidgetTest, GetCompositionRangeForSelection) { LoadHTML( "<div>NOT EDITABLE</div>" "<script> document.execCommand('selectAll'); </script>"); - gfx::Range range; - GetCompositionRange(&range); + gfx::Range range = LastCompositionRange(); // Selection range should not be treated as composition range. EXPECT_FALSE(range.IsValid()); } TEST_F(RenderWidgetTest, GetCompositionRangeInvalid) { LoadHTML("<div>NOT EDITABLE</div>"); - gfx::Range range; - GetCompositionRange(&range); + gfx::Range range = LastCompositionRange(); // If this test ever starts failing, one likely outcome is that WebRange // and gfx::Range::InvalidRange are no longer expressed in the same // values of start/end. @@ -334,7 +336,8 @@ TEST_F(RenderWidgetTest, PageFocusIme) { EXPECT_TRUE(GetInputMethodController()); // Verify the text input type. - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType()); + EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeText, + GetInputMethodController()->TextInputType()); // Commit some text. std::string text = "hello"; @@ -350,7 +353,8 @@ TEST_F(RenderWidgetTest, PageFocusIme) { EXPECT_TRUE(GetInputMethodController()); // The text input type should not change. - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType()); + EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeText, + GetInputMethodController()->TextInputType()); // Commit the text again. text = " world"; diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc index e1ed89aa710..7a5da56081f 100644 --- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc +++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc @@ -30,7 +30,6 @@ #include "ui/gl/gpu_preference.h" using blink::WebCoalescedInputEvent; -using blink::WebImeTextSpan; using blink::WebGestureEvent; using blink::WebInputEvent; using blink::WebInputEventResult; @@ -163,6 +162,28 @@ class PepperExternalWidgetClient : public blink::WebExternalWidgetClient { widget_->DidInitiatePaint(); } + void GetWidgetInputHandler( + blink::CrossVariantMojoReceiver< + blink::mojom::WidgetInputHandlerInterfaceBase> widget_input_receiver, + blink::CrossVariantMojoRemote< + blink::mojom::WidgetInputHandlerHostInterfaceBase> + widget_input_host_remote) override { + widget_->GetWidgetInputHandler(std::move(widget_input_receiver), + std::move(widget_input_host_remote)); + } + + void SendCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds) override { + return widget_->SendCompositionRangeChanged(range, character_bounds); + } + + bool HasCurrentImeGuard(bool request_to_show_virtual_keyboard) override { + return widget_->HasCurrentImeGuard(request_to_show_virtual_keyboard); + } + + void FocusChanged(bool enabled) override { widget_->FocusChanged(enabled); } + private: RenderWidgetFullscreenPepper* widget_; }; @@ -175,16 +196,14 @@ RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( const ScreenInfo& screen_info, PepperPluginInstanceImpl* plugin, const blink::WebURL& local_main_frame_url, - mojo::PendingReceiver<mojom::Widget> widget_receiver, mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget) { DCHECK_NE(MSG_ROUTING_NONE, routing_id); DCHECK(show_callback); RenderWidgetFullscreenPepper* render_widget = new RenderWidgetFullscreenPepper( - routing_id, compositor_deps, plugin, std::move(widget_receiver), - std::move(blink_widget_host), std::move(blink_widget), - local_main_frame_url); + routing_id, compositor_deps, plugin, std::move(blink_widget_host), + std::move(blink_widget), local_main_frame_url); render_widget->InitForPepperFullscreen(std::move(show_callback), render_widget->blink_widget_.get(), screen_info); @@ -195,15 +214,13 @@ RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( int32_t routing_id, CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, - mojo::PendingReceiver<mojom::Widget> widget_receiver, mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> mojo_widget_host, mojo::PendingAssociatedReceiver<blink::mojom::Widget> mojo_widget, blink::WebURL main_frame_url) : RenderWidget(routing_id, compositor_deps, /*hidden=*/false, - /*never_composited=*/false, - std::move(widget_receiver)), + /*never_composited=*/false), plugin_(plugin), mouse_lock_dispatcher_( std::make_unique<FullscreenMouseLockDispatcher>(this)), @@ -237,7 +254,7 @@ void RenderWidgetFullscreenPepper::Destroy() { void RenderWidgetFullscreenPepper::PepperDidChangeCursor( const ui::Cursor& cursor) { - DidChangeCursor(cursor); + blink_widget_->SetCursor(cursor); } void RenderWidgetFullscreenPepper::SetLayer(scoped_refptr<cc::Layer> layer) { diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h index 8c5f31d55e0..f9039222ad5 100644 --- a/chromium/content/renderer/render_widget_fullscreen_pepper.h +++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h @@ -43,7 +43,6 @@ class RenderWidgetFullscreenPepper : public RenderWidget, const ScreenInfo& screen_info, PepperPluginInstanceImpl* plugin, const blink::WebURL& local_main_frame_url, - mojo::PendingReceiver<mojom::Widget> widget_receiver, mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget); @@ -64,7 +63,6 @@ class RenderWidgetFullscreenPepper : public RenderWidget, int32_t routing_id, CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, - mojo::PendingReceiver<mojom::Widget> widget_receiver, mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget, blink::WebURL main_frame_url); diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc index 4f520250ce7..7e2a560a1eb 100644 --- a/chromium/content/renderer/render_widget_unittest.cc +++ b/chromium/content/renderer/render_widget_unittest.cc @@ -22,7 +22,6 @@ #include "cc/trees/layer_tree_host.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "content/common/frame_replication_state.h" -#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/common/visual_properties.h" @@ -30,7 +29,6 @@ #include "content/public/common/content_features.h" #include "content/public/test/fake_render_widget_host.h" #include "content/public/test/mock_render_thread.h" -#include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_process.h" #include "content/renderer/render_widget_delegate.h" @@ -40,7 +38,9 @@ #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" #include "third_party/blink/public/mojom/page/widget.mojom-test-utils.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/web/web_device_emulation_params.h" @@ -60,10 +60,9 @@ using testing::_; namespace blink { -namespace mojom { -bool operator==(const DidOverscrollParams& lhs, - const DidOverscrollParams& rhs) { +bool operator==(const InputHandlerProxy::DidOverscrollParams& lhs, + const InputHandlerProxy::DidOverscrollParams& rhs) { return lhs.accumulated_overscroll == rhs.accumulated_overscroll && lhs.latest_overscroll_delta == rhs.latest_overscroll_delta && lhs.current_fling_velocity == rhs.current_fling_velocity && @@ -71,7 +70,6 @@ bool operator==(const DidOverscrollParams& lhs, lhs.overscroll_behavior == rhs.overscroll_behavior; } -} // namespace mojom } // namespace blink namespace cc { @@ -97,52 +95,6 @@ enum { PASSIVE_LISTENER_UMA_ENUM_COUNT }; -class MockWidgetInputHandlerHost : public mojom::WidgetInputHandlerHost { - public: - MockWidgetInputHandlerHost() {} - MOCK_METHOD1(SetTouchActionFromMain, void(cc::TouchAction)); - - MOCK_METHOD3(SetWhiteListedTouchAction, - void(cc::TouchAction, - uint32_t, - blink::mojom::InputEventResultState)); - - MOCK_METHOD1(DidOverscroll, void(blink::mojom::DidOverscrollParamsPtr)); - - MOCK_METHOD0(DidStopFlinging, void()); - - MOCK_METHOD0(DidStartScrollingViewport, void()); - - MOCK_METHOD0(ImeCancelComposition, void()); - - MOCK_METHOD2(ImeCompositionRangeChanged, - void(const gfx::Range&, const std::vector<gfx::Rect>&)); - - MOCK_METHOD1(SetMouseCapture, void(bool)); - - MOCK_METHOD0(UnlockMouse, void()); - - MOCK_METHOD4(RequestMouseLock, - void((bool, - bool, - bool, - mojom::WidgetInputHandlerHost::RequestMouseLockCallback))); - - MOCK_METHOD2(RequestMouseLockChange, - void((bool, - mojom::WidgetInputHandlerHost::RequestMouseLockCallback))); - - mojo::PendingRemote<mojom::WidgetInputHandlerHost> - BindNewPipeAndPassRemote() { - return receiver_.BindNewPipeAndPassRemote(); - } - - private: - mojo::Receiver<mojom::WidgetInputHandlerHost> receiver_{this}; - - DISALLOW_COPY_AND_ASSIGN(MockWidgetInputHandlerHost); -}; - // Since std::unique_ptr isn't copyable we can't use the // MockCallback template. class MockHandledEventCallback { @@ -151,19 +103,20 @@ class MockHandledEventCallback { MOCK_METHOD4_T(Run, void(blink::mojom::InputEventResultState, const ui::LatencyInfo&, - blink::mojom::DidOverscrollParams* overscroll, + blink::InputHandlerProxy::DidOverscrollParams*, base::Optional<cc::TouchAction>)); - HandledEventCallback GetCallback() { + blink::WebWidget::HandledEventCallback GetCallback() { return base::BindOnce(&MockHandledEventCallback::HandleCallback, base::Unretained(this)); } private: - void HandleCallback(blink::mojom::InputEventResultState ack_state, - const ui::LatencyInfo& latency_info, - blink::mojom::DidOverscrollParamsPtr overscroll, - base::Optional<cc::TouchAction> touch_action) { + void HandleCallback( + blink::mojom::InputEventResultState ack_state, + const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams> overscroll, + base::Optional<cc::TouchAction> touch_action) { Run(ack_state, latency_info, overscroll.get(), touch_action); } @@ -182,6 +135,15 @@ class MockWebExternalWidgetClient : public blink::WebExternalWidgetClient { blink::WebInputEventResult(const blink::WebCoalescedInputEvent&)); MOCK_METHOD1(RequestNewLayerTreeFrameSink, void(LayerTreeFrameSinkCallback)); MOCK_METHOD0(DidCommitAndDrawCompositorFrame, void()); + MOCK_METHOD1(WillHandleGestureEvent, bool(const blink::WebGestureEvent&)); + MOCK_METHOD4(DidHandleGestureScrollEvent, + void(const blink::WebGestureEvent& gesture_event, + const gfx::Vector2dF& unused_delta, + const cc::OverscrollBehavior& overscroll_behavior, + bool event_processed)); + + // Because we mock DispatchBufferedTouchEvents indicate we have support. + bool SupportsBufferedTouchEvents() override { return true; } }; } // namespace @@ -192,67 +154,44 @@ class InteractiveRenderWidget : public RenderWidget { : RenderWidget(++next_routing_id_, compositor_deps, /*is_hidden=*/false, - /*never_composited=*/false, - mojo::NullReceiver()) {} + /*never_composited=*/false) {} void Init(blink::WebWidget* widget, const ScreenInfo& screen_info) { Initialize(base::NullCallback(), widget, screen_info); - - mock_input_handler_host_ = std::make_unique<MockWidgetInputHandlerHost>(); - - widget_input_handler_manager_->AddInterface( - mojo::PendingReceiver<mojom::WidgetInputHandler>(), - mock_input_handler_host_->BindNewPipeAndPassRemote()); } using RenderWidget::Close; void SendInputEvent(const blink::WebInputEvent& event, - HandledEventCallback callback) { - HandleInputEvent( + blink::WebWidget::HandledEventCallback callback) { + GetWebWidget()->ProcessInputEventSynchronously( blink::WebCoalescedInputEvent(event.Clone(), {}, {}, ui::LatencyInfo()), std::move(callback)); } - void set_always_overscroll(bool overscroll) { - always_overscroll_ = overscroll; - } - - MOCK_METHOD4(ObserveGestureEventAndResult, - void(const blink::WebGestureEvent& gesture_event, - const gfx::Vector2dF& unused_delta, - const cc::OverscrollBehavior& overscroll_behavior, - bool event_processed)); - IPC::TestSink* sink() { return &sink_; } - MockWidgetInputHandlerHost* mock_input_handler_host() { - return mock_input_handler_host_.get(); - } - const viz::LocalSurfaceIdAllocation& local_surface_id_allocation_from_parent() const { return local_surface_id_allocation_from_parent_; } - protected: - // Overridden from RenderWidget: - bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override { - if (always_overscroll_ && - event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate) { - DidOverscroll(gfx::Vector2dF(event.data.scroll_update.delta_x, - event.data.scroll_update.delta_y), - gfx::Vector2dF(event.data.scroll_update.delta_x, - event.data.scroll_update.delta_y), - event.PositionInWidget(), - gfx::Vector2dF(event.data.scroll_update.velocity_x, - event.data.scroll_update.velocity_y)); + bool OverscrollGestureEvent(const blink::WebGestureEvent& event) { + if (event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate) { + GetWebWidget()->DidOverscrollForTesting( + gfx::Vector2dF(event.data.scroll_update.delta_x, + event.data.scroll_update.delta_y), + gfx::Vector2dF(event.data.scroll_update.delta_x, + event.data.scroll_update.delta_y), + event.PositionInWidget(), + gfx::Vector2dF(event.data.scroll_update.velocity_x, + event.data.scroll_update.velocity_y)); return true; } - return false; } + protected: bool Send(IPC::Message* msg) override { sink_.OnMessageReceived(*msg); delete msg; @@ -261,8 +200,6 @@ class InteractiveRenderWidget : public RenderWidget { private: IPC::TestSink sink_; - bool always_overscroll_ = false; - std::unique_ptr<MockWidgetInputHandlerHost> mock_input_handler_host_; static int next_routing_id_; DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget); @@ -273,6 +210,27 @@ int InteractiveRenderWidget::next_routing_id_ = 0; class RenderWidgetUnittest : public testing::Test { public: void SetUp() override { + mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget_remote; + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> + frame_widget_receiver = + frame_widget_remote + .BindNewEndpointAndPassDedicatedReceiverForTesting(); + + mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost> + frame_widget_host_receiver = + frame_widget_host + .BindNewEndpointAndPassDedicatedReceiverForTesting(); + + mojo::AssociatedRemote<blink::mojom::Widget> widget_remote; + mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget_receiver = + widget_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + + mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host; + mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> + widget_host_receiver = + widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + web_view_ = blink::WebView::Create(/*client=*/&web_view_client_, /*is_hidden=*/false, /*compositing_enabled=*/true, nullptr, @@ -282,15 +240,9 @@ class RenderWidgetUnittest : public testing::Test { web_view_, &web_frame_client_, nullptr, base::UnguessableToken::Create(), nullptr); web_frame_widget_ = blink::WebFrameWidget::CreateForMainFrame( - widget_.get(), web_local_frame_, - blink::CrossVariantMojoAssociatedRemote< - blink::mojom::FrameWidgetHostInterfaceBase>(), - blink::CrossVariantMojoAssociatedReceiver< - blink::mojom::FrameWidgetInterfaceBase>(), - blink::CrossVariantMojoAssociatedRemote< - blink::mojom::WidgetHostInterfaceBase>(), - blink::CrossVariantMojoAssociatedReceiver< - blink::mojom::WidgetInterfaceBase>()); + widget_.get(), web_local_frame_, frame_widget_host.Unbind(), + std::move(frame_widget_receiver), widget_host.Unbind(), + std::move(widget_receiver)); widget_->Init(web_frame_widget_, ScreenInfo()); web_view_->DidAttachLocalMainFrame(); } @@ -415,29 +367,31 @@ TEST_F(RenderWidgetExternalWidgetUnittest, CursorChange) { auto set_cursor_interceptor = std::make_unique<SetCursorInterceptor>(render_widget_host()); - widget()->DidChangeCursor(cursor); + widget()->GetWebWidget()->SetCursor(cursor); render_widget_host()->widget_host_receiver_for_testing().FlushForTesting(); EXPECT_EQ(set_cursor_interceptor->set_cursor_count(), 1); - widget()->DidChangeCursor(cursor); + widget()->GetWebWidget()->SetCursor(cursor); render_widget_host()->widget_host_receiver_for_testing().FlushForTesting(); EXPECT_EQ(set_cursor_interceptor->set_cursor_count(), 1); EXPECT_CALL(*mock_web_external_widget_client(), HandleInputEvent(_)) .WillOnce(::testing::Return(blink::WebInputEventResult::kNotHandled)); - widget()->SendInputEvent(SyntheticWebMouseEventBuilder::Build( + widget()->SendInputEvent(blink::SyntheticWebMouseEventBuilder::Build( blink::WebInputEvent::Type::kMouseLeave), - HandledEventCallback()); + base::DoNothing()); render_widget_host()->widget_host_receiver_for_testing().FlushForTesting(); EXPECT_EQ(set_cursor_interceptor->set_cursor_count(), 1); - widget()->DidChangeCursor(cursor); + widget()->GetWebWidget()->SetCursor(cursor); render_widget_host()->widget_host_receiver_for_testing().FlushForTesting(); EXPECT_EQ(set_cursor_interceptor->set_cursor_count(), 2); } TEST_F(RenderWidgetExternalWidgetUnittest, EventOverscroll) { - widget()->set_always_overscroll(true); + ON_CALL(*mock_web_external_widget_client(), WillHandleGestureEvent(_)) + .WillByDefault(testing::Invoke( + widget(), &InteractiveRenderWidget::OverscrollGestureEvent)); EXPECT_CALL(*mock_web_external_widget_client(), HandleInputEvent(_)) .WillRepeatedly( @@ -450,7 +404,7 @@ TEST_F(RenderWidgetExternalWidgetUnittest, EventOverscroll) { scroll.data.scroll_update.delta_y = 10; MockHandledEventCallback handled_event; - blink::mojom::DidOverscrollParams expected_overscroll; + blink::InputHandlerProxy::DidOverscrollParams expected_overscroll; expected_overscroll.latest_overscroll_delta = gfx::Vector2dF(0, 10); expected_overscroll.accumulated_overscroll = gfx::Vector2dF(0, 10); expected_overscroll.causal_event_viewport_point = gfx::PointF(-10, 0); @@ -466,7 +420,7 @@ TEST_F(RenderWidgetExternalWidgetUnittest, EventOverscroll) { } TEST_F(RenderWidgetExternalWidgetUnittest, RenderWidgetInputEventUmaMetrics) { - SyntheticWebTouchEvent touch; + blink::SyntheticWebTouchEvent touch; touch.PressPoint(10, 10); touch.touch_start_or_first_touch_move = true; @@ -480,25 +434,25 @@ TEST_F(RenderWidgetExternalWidgetUnittest, RenderWidgetInputEventUmaMetrics) { .WillRepeatedly( ::testing::Return(blink::WebInputEventResult::kNotHandled)); - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_CANCELABLE, 1); touch.dispatch_type = blink::WebInputEvent::DispatchType::kEventNonBlocking; - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE, 1); touch.dispatch_type = blink::WebInputEvent::DispatchType::kListenersNonBlockingPassive; - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_PASSIVE, 1); touch.dispatch_type = blink::WebInputEvent::DispatchType::kListenersForcedNonBlockingDueToFling; - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount( EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING, 1); @@ -507,7 +461,7 @@ TEST_F(RenderWidgetExternalWidgetUnittest, RenderWidgetInputEventUmaMetrics) { touch.touch_start_or_first_touch_move = true; touch.dispatch_type = blink::WebInputEvent::DispatchType::kListenersForcedNonBlockingDueToFling; - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount( EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING, 2); @@ -518,7 +472,7 @@ TEST_F(RenderWidgetExternalWidgetUnittest, RenderWidgetInputEventUmaMetrics) { .WillOnce( ::testing::Return(blink::WebInputEventResult::kHandledSuppressed)); touch.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking; - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED, 1); @@ -528,7 +482,7 @@ TEST_F(RenderWidgetExternalWidgetUnittest, RenderWidgetInputEventUmaMetrics) { .WillOnce( ::testing::Return(blink::WebInputEventResult::kHandledApplication)); touch.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking; - widget()->SendInputEvent(touch, HandledEventCallback()); + widget()->SendInputEvent(touch, base::DoNothing()); histogram_tester().ExpectBucketCount( EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED, 1); @@ -544,14 +498,16 @@ TEST_F(RenderWidgetExternalWidgetUnittest, SendElasticOverscrollForTouchpad) { scroll.SetPositionInWidget(gfx::PointF(-10, 0)); scroll.data.scroll_update.delta_y = 10; - // We only really care that ObserveGestureEventAndResult was called; we + // We only really care that DidHandleGestureScrollEvent was called; we // therefore suppress the warning for the call to // mock_webwidget()->HandleInputEvent(). - EXPECT_CALL(*widget(), ObserveGestureEventAndResult(_, _, _, _)).Times(1); + EXPECT_CALL(*mock_web_external_widget_client(), + DidHandleGestureScrollEvent(_, _, _, _)) + .Times(1); EXPECT_CALL(*mock_web_external_widget_client(), HandleInputEvent(_)) .Times(testing::AnyNumber()); - widget()->SendInputEvent(scroll, HandledEventCallback()); + widget()->SendInputEvent(scroll, base::DoNothing()); } // Ensures that the compositor thread gets sent the gesture event & overscroll @@ -565,14 +521,16 @@ TEST_F(RenderWidgetExternalWidgetUnittest, scroll.SetPositionInWidget(gfx::PointF(-10, 0)); scroll.data.scroll_update.delta_y = 10; - // We only really care that ObserveGestureEventAndResult was called; we + // We only really care that DidHandleGestureScrollEvent was called; we // therefore suppress the warning for the call to // mock_webwidget()->HandleInputEvent(). - EXPECT_CALL(*widget(), ObserveGestureEventAndResult(_, _, _, _)).Times(1); + EXPECT_CALL(*mock_web_external_widget_client(), + DidHandleGestureScrollEvent(_, _, _, _)) + .Times(1); EXPECT_CALL(*mock_web_external_widget_client(), HandleInputEvent(_)) .Times(testing::AnyNumber()); - widget()->SendInputEvent(scroll, HandledEventCallback()); + widget()->SendInputEvent(scroll, base::DoNothing()); } // Tests that if a RenderWidget is auto-resized, it requests a new @@ -690,7 +648,7 @@ TEST_F(RenderWidgetUnittest, ForceSendMetadataOnInput) { // We should not have any force send metadata requests at start. EXPECT_FALSE(layer_tree_host->TakeForceSendMetadataRequest()); // ShowVirtualKeyboard will trigger a text input state update. - widget()->ShowVirtualKeyboard(); + widget()->GetWebWidget()->ShowVirtualKeyboard(); // We should now have a force send metadata request. EXPECT_TRUE(layer_tree_host->TakeForceSendMetadataRequest()); } diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc index 9b6fb9c13ed..a4382a6afa3 100644 --- a/chromium/content/renderer/renderer_blink_platform_impl.cc +++ b/chromium/content/renderer/renderer_blink_platform_impl.cc @@ -165,13 +165,10 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl( : nullptr), sudden_termination_disables_(0), is_locked_to_site_(false), - default_task_runner_(main_thread_scheduler->DefaultTaskRunner()), main_thread_scheduler_(main_thread_scheduler) { // RenderThread may not exist in some tests. if (RenderThreadImpl::current()) { - io_runner_ = RenderThreadImpl::current()->GetIOTaskRunner(); - thread_safe_sender_ = RenderThreadImpl::current()->thread_safe_sender(); #if defined(OS_LINUX) mojo::PendingRemote<font_service::mojom::FontService> font_service; RenderThreadImpl::current()->BindHostReceiver( @@ -228,13 +225,13 @@ RendererBlinkPlatformImpl::CreateCodeCacheLoader() { std::unique_ptr<blink::WebURLLoaderFactory> RendererBlinkPlatformImpl::WrapURLLoaderFactory( - mojo::ScopedMessagePipeHandle url_loader_factory_handle) { + blink::CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase> + url_loader_factory) { return std::make_unique<WebURLLoaderFactoryImpl>( RenderThreadImpl::current()->resource_dispatcher()->GetWeakPtr(), base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( mojo::PendingRemote<network::mojom::URLLoaderFactory>( - std::move(url_loader_factory_handle), - network::mojom::URLLoaderFactory::Version_))); + std::move(url_loader_factory)))); } std::unique_ptr<blink::WebURLLoaderFactory> diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h index 80490f5b8d5..59d7d92cf5f 100644 --- a/chromium/content/renderer/renderer_blink_platform_impl.h +++ b/chromium/content/renderer/renderer_blink_platform_impl.h @@ -57,7 +57,6 @@ class RasterContextProvider; namespace content { class ChildURLLoaderFactoryBundle; -class ThreadSafeSender; class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { public: @@ -192,7 +191,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { std::unique_ptr<blink::CodeCacheLoader> CreateCodeCacheLoader() override; std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory( - mojo::ScopedMessagePipeHandle url_loader_factory_handle) override; + blink::CrossVariantMojoRemote< + network::mojom::URLLoaderFactoryInterfaceBase> url_loader_factory) + override; std::unique_ptr<blink::WebURLLoaderFactory> WrapSharedURLLoaderFactory( scoped_refptr<network::SharedURLLoaderFactory> factory) override; @@ -217,8 +218,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { // Return the mojo interface for making CodeCache calls. blink::mojom::CodeCacheHost& GetCodeCacheHost(); - scoped_refptr<base::SingleThreadTaskRunner> io_runner_; - #if defined(OS_LINUX) || defined(OS_MACOSX) std::unique_ptr<blink::WebSandboxSupport> sandbox_support_; #endif @@ -232,9 +231,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { // If true, the renderer process is locked to a site. bool is_locked_to_site_; - scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; - scoped_refptr<ThreadSafeSender> thread_safe_sender_; - // NOT OWNED blink::scheduler::WebThreadScheduler* main_thread_scheduler_; diff --git a/chromium/content/renderer/savable_resources.cc b/chromium/content/renderer/savable_resources.cc deleted file mode 100644 index c6515bc5550..00000000000 --- a/chromium/content/renderer/savable_resources.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/savable_resources.h" - -#include <set> - -#include "base/compiler_specific.h" -#include "base/strings/string_util.h" -#include "content/public/common/url_utils.h" -#include "content/renderer/render_frame_impl.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/public/web/web_document.h" -#include "third_party/blink/public/web/web_element.h" -#include "third_party/blink/public/web/web_element_collection.h" -#include "third_party/blink/public/web/web_input_element.h" -#include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_node.h" -#include "third_party/blink/public/web/web_view.h" - -using blink::WebDocument; -using blink::WebElement; -using blink::WebElementCollection; -using blink::WebFrame; -using blink::WebInputElement; -using blink::WebLocalFrame; -using blink::WebNode; -using blink::WebString; -using blink::WebVector; -using blink::WebView; - -namespace content { -namespace { - -// Returns |true| if |web_frame| contains (or should be assumed to contain) -// a html document. -bool DoesFrameContainHtmlDocument(WebFrame* web_frame, - const WebElement& element) { - if (web_frame->IsWebLocalFrame()) { - WebDocument doc = web_frame->ToWebLocalFrame()->GetDocument(); - return doc.IsHTMLDocument() || doc.IsXHTMLDocument(); - } - - // Cannot inspect contents of a remote frame, so we use a heuristic: - // Assume that <iframe> and <frame> elements contain a html document, - // and other elements (i.e. <object>) contain plugins or other resources. - // If the heuristic is wrong (i.e. the remote frame in <object> does - // contain an html document), then things will still work, but with the - // following caveats: 1) original frame content will be saved and 2) links - // in frame's html doc will not be rewritten to point to locally saved - // files. - return element.HasHTMLTagName("iframe") || element.HasHTMLTagName("frame"); -} - -// If present and valid, then push the link associated with |element| -// into either SavableResourcesResult::subframes or -// SavableResourcesResult::resources_list. -void GetSavableResourceLinkForElement( - const WebElement& element, - const WebDocument& current_doc, - SavableResourcesResult* result) { - // Get absolute URL. - WebString link_attribute_value = GetSubResourceLinkFromElement(element); - GURL element_url = current_doc.CompleteURL(link_attribute_value); - - // See whether to report this element as a subframe. - WebFrame* web_frame = WebFrame::FromFrameOwnerElement(element); - if (web_frame && DoesFrameContainHtmlDocument(web_frame, element)) { - SavableSubframe subframe; - subframe.original_url = element_url; - subframe.routing_id = RenderFrame::GetRoutingIdForWebFrame(web_frame); - result->subframes->push_back(subframe); - return; - } - - // Check whether the node has sub resource URL or not. - if (link_attribute_value.IsNull()) - return; - - // Ignore invalid URL. - if (!element_url.is_valid()) - return; - - // Ignore those URLs which are not standard protocols. Because FTP - // protocol does no have cache mechanism, we will skip all - // sub-resources if they use FTP protocol. - if (!element_url.SchemeIsHTTPOrHTTPS() && - !element_url.SchemeIs(url::kFileScheme)) - return; - - result->resources_list->push_back(element_url); -} - -} // namespace - -bool GetSavableResourceLinksForFrame(WebLocalFrame* current_frame, - SavableResourcesResult* result) { - // Get current frame's URL. - GURL current_frame_url = current_frame->GetDocument().Url(); - - // If url of current frame is invalid, ignore it. - if (!current_frame_url.is_valid()) - return false; - - // If url of current frame is not a savable protocol, ignore it. - if (!IsSavableURL(current_frame_url)) - return false; - - // Get current using document. - WebDocument current_doc = current_frame->GetDocument(); - // Go through all descent nodes. - WebElementCollection all = current_doc.All(); - // Go through all elements in this frame. - for (WebElement element = all.FirstItem(); !element.IsNull(); - element = all.NextItem()) { - GetSavableResourceLinkForElement(element, - current_doc, - result); - } - - return true; -} - -WebString GetSubResourceLinkFromElement(const WebElement& element) { - const char* attribute_name = nullptr; - if (element.HasHTMLTagName("img") || element.HasHTMLTagName("frame") || - element.HasHTMLTagName("iframe") || element.HasHTMLTagName("script")) { - attribute_name = "src"; - } else if (element.HasHTMLTagName("input")) { - const WebInputElement input = element.ToConst<WebInputElement>(); - if (input.IsImageButton()) { - attribute_name = "src"; - } - } else if (element.HasHTMLTagName("body") || - element.HasHTMLTagName("table") || element.HasHTMLTagName("tr") || - element.HasHTMLTagName("td")) { - attribute_name = "background"; - } else if (element.HasHTMLTagName("blockquote") || - element.HasHTMLTagName("q") || element.HasHTMLTagName("del") || - element.HasHTMLTagName("ins")) { - attribute_name = "cite"; - } else if (element.HasHTMLTagName("object")) { - attribute_name = "data"; - } else if (element.HasHTMLTagName("link")) { - // If the link element is not linked to css, ignore it. - WebString type = element.GetAttribute("type"); - WebString rel = element.GetAttribute("rel"); - if ((type.ContainsOnlyASCII() && - base::LowerCaseEqualsASCII(type.Ascii(), "text/css")) || - (rel.ContainsOnlyASCII() && - base::LowerCaseEqualsASCII(rel.Ascii(), "stylesheet"))) { - // TODO(jnd): Add support for extracting links of sub-resources which - // are inside style-sheet such as @import, url(), etc. - // See bug: http://b/issue?id=1111667. - attribute_name = "href"; - } - } - if (!attribute_name) - return WebString(); - WebString value = element.GetAttribute(WebString::FromUTF8(attribute_name)); - // If value has content and not start with "javascript:" then return it, - // otherwise return NULL. - if (!value.IsNull() && !value.IsEmpty() && - !base::StartsWith(value.Utf8(), - "javascript:", base::CompareCase::INSENSITIVE_ASCII)) - return value; - - return WebString(); -} - -} // namespace content diff --git a/chromium/content/renderer/savable_resources.h b/chromium/content/renderer/savable_resources.h deleted file mode 100644 index ee314deafc2..00000000000 --- a/chromium/content/renderer/savable_resources.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_SAVABLE_RESOURCES_H_ -#define CONTENT_RENDERER_SAVABLE_RESOURCES_H_ - -#include <string> -#include <vector> - -#include "base/macros.h" -#include "content/common/content_export.h" -#include "content/common/savable_subframe.h" -#include "services/network/public/mojom/referrer_policy.mojom.h" -#include "url/gurl.h" - -namespace blink { -class WebElement; -class WebLocalFrame; -class WebString; -} - -// A collection of operations that access the underlying WebKit DOM directly. -namespace content { - -// Structure for storage the result of getting all savable resource links -// for current page. The consumer of the SavableResourcesResult is responsible -// for keeping these pointers valid for the lifetime of the -// SavableResourcesResult instance. -struct SavableResourcesResult { - // Links of all savable resources. - std::vector<GURL>* resources_list; - - // Subframes. - std::vector<SavableSubframe>* subframes; - - // Constructor. - SavableResourcesResult( - std::vector<GURL>* resources_list, - std::vector<SavableSubframe>* subframes) - : resources_list(resources_list), - subframes(subframes) {} - - private: - DISALLOW_COPY_AND_ASSIGN(SavableResourcesResult); -}; - -// Get all the savable resource links from the specified |frame|. -// Returns true if the saved resources links have been saved successfully. -// Otherwise returns false (i.e. if the frame contains a non-savable content). -CONTENT_EXPORT bool GetSavableResourceLinksForFrame( - blink::WebLocalFrame* frame, - SavableResourcesResult* result); - -// Returns the value in an elements resource url attribute. For IMG, SCRIPT or -// INPUT TYPE=image, returns the value in "src". For LINK TYPE=text/css, returns -// the value in "href". For BODY, TABLE, TR, TD, returns the value in -// "background". For BLOCKQUOTE, Q, DEL, INS, returns the value in "cite" -// attribute. Otherwise returns a null WebString. -CONTENT_EXPORT blink::WebString GetSubResourceLinkFromElement( - const blink::WebElement& element); - -} // namespace content - -#endif // CONTENT_RENDERER_SAVABLE_RESOURCES_H_ diff --git a/chromium/content/renderer/savable_resources_browsertest.cc b/chromium/content/renderer/savable_resources_browsertest.cc index c8638aae2c7..b7b247a036d 100644 --- a/chromium/content/renderer/savable_resources_browsertest.cc +++ b/chromium/content/renderer/savable_resources_browsertest.cc @@ -13,13 +13,16 @@ #include "content/public/test/browser_test.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" -#include "content/renderer/savable_resources.h" #include "content/shell/browser/shell.h" #include "net/base/filename_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/mojom/frame/frame.mojom.h" +#include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/web/web_frame.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_savable_resources_test_support.h" namespace content { @@ -59,22 +62,36 @@ class SavableResourcesTest : public ContentBrowserTest { const UrlVectorMatcher& expected_subframe_urls_matcher, const GURL& file_url, int render_frame_routing_id) { - // Get all savable resource links for the page. - std::vector<GURL> resources_list; - std::vector<SavableSubframe> subframes; - SavableResourcesResult result(&resources_list, &subframes); - RenderFrame* render_frame = RenderFrame::FromRoutingID(render_frame_routing_id); - ASSERT_TRUE(GetSavableResourceLinksForFrame( - render_frame->GetWebFrame(), &result)); + mojo::AssociatedRemote<blink::mojom::LocalFrame> local_frame; + render_frame->GetRemoteAssociatedInterfaces()->GetInterface( + local_frame.BindNewEndpointAndPassReceiver()); + local_frame->GetSavableResourceLinks( + base::BindOnce(&SavableResourcesTest::GetSavableResourceLinksCallback, + base::Unretained(this), expected_resources_matcher, + expected_subframe_urls_matcher)); + } + void GetSavableResourceLinksCallback( + const UrlVectorMatcher& expected_resources_matcher, + const UrlVectorMatcher& expected_subframe_urls_matcher, + blink::mojom::GetSavableResourceLinksReplyPtr reply) { + if (!reply) { + DCHECK(false) + << "blink::mojom::GetSavableResourceLinks returnes nullptr."; + return; + } + + std::vector<GURL> resources_list; + for (auto url : reply->resources_list) + resources_list.push_back(url); EXPECT_THAT(resources_list, expected_resources_matcher); std::vector<GURL> subframe_original_urls; - for (const SavableSubframe& subframe : subframes) { - subframe_original_urls.push_back(subframe.original_url); + for (auto& subframe : reply->subframes) { + subframe_original_urls.push_back(subframe->original_url); } EXPECT_THAT(subframe_original_urls, expected_subframe_urls_matcher); } diff --git a/chromium/content/renderer/service_worker/controller_service_worker_connector.h b/chromium/content/renderer/service_worker/controller_service_worker_connector.h index fffa08afadb..43276e168db 100644 --- a/chromium/content/renderer/service_worker/controller_service_worker_connector.h +++ b/chromium/content/renderer/service_worker/controller_service_worker_connector.h @@ -121,8 +121,7 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector base::ObserverList<Observer>::Unchecked observer_list_; // The web-exposed client id, used for FetchEvent#clientId (i.e., - // ServiceWorkerProviderHost::client_uuid and not - // ServiceWorkerProviderHost::provider_id). + // ServiceWorkerContainerHost::client_uuid). std::string client_id_; DISALLOW_COPY_AND_ASSIGN(ControllerServiceWorkerConnector); diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc index 34af7fec6ce..e46e3ce0623 100644 --- a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc +++ b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc @@ -13,7 +13,6 @@ #include "content/child/scoped_child_process_reference.h" #include "content/common/service_worker/service_worker_utils.h" #include "content/public/common/content_client.h" -#include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/service_worker_context_client.h" #include "content/renderer/worker/fetch_client_settings_object_helpers.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -30,6 +29,7 @@ namespace content { // static void EmbeddedWorkerInstanceClientImpl::Create( scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver) { // This won't be leaked because the lifetime will be managed internally. @@ -38,15 +38,18 @@ void EmbeddedWorkerInstanceClientImpl::Create( // a chance to stop by calling TerminateWorkerContext() and waiting // before destructing. new EmbeddedWorkerInstanceClientImpl(std::move(receiver), - std::move(initiator_thread_task_runner)); + std::move(initiator_thread_task_runner), + cors_exempt_header_list); } void EmbeddedWorkerInstanceClientImpl::CreateForRequest( scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver) { EmbeddedWorkerInstanceClientImpl::Create( - std::move(initiator_thread_task_runner), std::move(receiver)); + std::move(initiator_thread_task_runner), cors_exempt_header_list, + std::move(receiver)); } void EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed() { @@ -87,7 +90,7 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( std::move(params->subresource_loader_factories), std::move(params->subresource_loader_updater), params->script_url_to_skip_throttling, initiator_thread_task_runner_, - params->service_worker_route_id); + params->service_worker_route_id, cors_exempt_header_list_); // Record UMA to indicate StartWorker is received on renderer. StartWorkerHistogramEnum metric = params->is_installed ? StartWorkerHistogramEnum::RECEIVED_ON_INSTALLED @@ -105,8 +108,8 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( installed_scripts_manager_params = std::make_unique<blink::WebServiceWorkerInstalledScriptsManagerParams>( std::move(params->installed_scripts_info->installed_urls), - params->installed_scripts_info->manager_receiver.PassPipe(), - params->installed_scripts_info->manager_host_remote.PassPipe()); + std::move(params->installed_scripts_info->manager_receiver), + std::move(params->installed_scripts_info->manager_host_remote)); } auto worker = @@ -114,8 +117,8 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( service_worker_context_client_->StartWorkerContextOnInitiatorThread( std::move(worker), std::move(start_data), std::move(installed_scripts_manager_params), - params->content_settings_proxy.PassPipe(), cache_storage.PassPipe(), - browser_interface_broker.PassPipe()); + std::move(params->content_settings_proxy), std::move(cache_storage), + std::move(browser_interface_broker)); } void EmbeddedWorkerInstanceClientImpl::StopWorker() { @@ -128,9 +131,11 @@ void EmbeddedWorkerInstanceClientImpl::StopWorker() { EmbeddedWorkerInstanceClientImpl::EmbeddedWorkerInstanceClientImpl( mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver, - scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list) : receiver_(this, std::move(receiver)), - initiator_thread_task_runner_(std::move(initiator_thread_task_runner)) { + initiator_thread_task_runner_(std::move(initiator_thread_task_runner)), + cors_exempt_header_list_(cors_exempt_header_list) { DCHECK(initiator_thread_task_runner_->BelongsToCurrentThread()); receiver_.set_disconnect_handler(base::BindOnce( &EmbeddedWorkerInstanceClientImpl::OnError, base::Unretained(this))); diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h index 1e7bb540976..085104e81b0 100644 --- a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h +++ b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h @@ -46,6 +46,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstanceClientImpl // instead of just creating an instance of EmbeddedWorkerInstanceClient. static void Create( scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver); @@ -54,6 +55,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstanceClientImpl // service_manager::BinderRegistry. static void CreateForRequest( scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver); @@ -72,7 +74,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstanceClientImpl EmbeddedWorkerInstanceClientImpl( mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver, - scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list); // blink::mojom::EmbeddedWorkerInstanceClient implementation void StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params) override; @@ -89,6 +92,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstanceClientImpl // StartWorker(). scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner_; + std::vector<std::string> cors_exempt_header_list_; + // nullptr means worker is not running. std::unique_ptr<ServiceWorkerContextClient> service_worker_context_client_; diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc index a6f1f799c44..77df196f12c 100644 --- a/chromium/content/renderer/service_worker/service_worker_context_client.cc +++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc @@ -47,6 +47,7 @@ #include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" #include "third_party/blink/public/mojom/blob/blob_registry.mojom.h" +#include "third_party/blink/public/mojom/browser_interface_broker.mojom.h" #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h" @@ -112,7 +113,8 @@ ServiceWorkerContextClient::ServiceWorkerContextClient( subresource_loader_updater, const GURL& script_url_to_skip_throttling, scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, - int32_t service_worker_route_id) + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list) : service_worker_version_id_(service_worker_version_id), service_worker_scope_(service_worker_scope), script_url_(script_url), @@ -128,7 +130,8 @@ ServiceWorkerContextClient::ServiceWorkerContextClient( std::move(subresource_loader_updater)), owner_(owner), start_timing_(std::move(start_timing)), - service_worker_route_id_(service_worker_route_id) { + service_worker_route_id_(service_worker_route_id), + cors_exempt_header_list_(cors_exempt_header_list) { DCHECK(initiator_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(owner_); DCHECK(subresource_loaders); @@ -176,14 +179,16 @@ void ServiceWorkerContextClient::StartWorkerContextOnInitiatorThread( std::unique_ptr<blink::WebEmbeddedWorkerStartData> start_data, std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManagerParams> installed_scripts_manager_params, - mojo::ScopedMessagePipeHandle content_settings_handle, - mojo::ScopedMessagePipeHandle cache_storage, - mojo::ScopedMessagePipeHandle browser_interface_broker) { + mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy> + content_settings, + mojo::PendingRemote<blink::mojom::CacheStorage> cache_storage, + mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> + browser_interface_broker) { DCHECK(initiator_thread_task_runner_->RunsTasksInCurrentSequence()); worker_ = std::move(worker); worker_->StartWorkerContext( std::move(start_data), std::move(installed_scripts_manager_params), - std::move(content_settings_handle), std::move(cache_storage), + std::move(content_settings), std::move(cache_storage), std::move(browser_interface_broker), initiator_thread_task_runner_); } @@ -193,15 +198,14 @@ blink::WebEmbeddedWorker& ServiceWorkerContextClient::worker() { } void ServiceWorkerContextClient::WorkerReadyForInspectionOnInitiatorThread( - mojo::ScopedMessagePipeHandle devtools_agent_remote, - mojo::ScopedMessagePipeHandle devtools_agent_host_receiver) { + blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + blink::CrossVariantMojoReceiver< + blink::mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) { DCHECK(initiator_thread_task_runner_->RunsTasksInCurrentSequence()); - mojo::PendingRemote<blink::mojom::DevToolsAgent> agent_remote( - std::move(devtools_agent_remote), blink::mojom::DevToolsAgent::Version_); - mojo::PendingReceiver<blink::mojom::DevToolsAgentHost> receiver( - std::move(devtools_agent_host_receiver)); - instance_host_->OnReadyForInspection(std::move(agent_remote), - std::move(receiver)); + instance_host_->OnReadyForInspection(std::move(devtools_agent_remote), + std::move(devtools_agent_host_receiver)); } void ServiceWorkerContextClient::FailedToFetchClassicScript() { @@ -241,10 +245,10 @@ void ServiceWorkerContextClient::WorkerContextStarted( context_ = std::make_unique<WorkerContextData>(this); DCHECK(pending_service_worker_receiver_.is_valid()); - proxy_->BindServiceWorker(pending_service_worker_receiver_.PassPipe()); + proxy_->BindServiceWorker(std::move(pending_service_worker_receiver_)); DCHECK(controller_receiver_.is_valid()); - proxy_->BindControllerServiceWorker(controller_receiver_.PassPipe()); + proxy_->BindControllerServiceWorker(std::move(controller_receiver_)); GetContentClient() ->renderer() @@ -386,7 +390,8 @@ ServiceWorkerContextClient::CreateWorkerFetchContextOnInitiatorThread() { ->renderer() ->CreateWebSocketHandshakeThrottleProvider(), std::move(preference_watcher_receiver_), - std::move(pending_subresource_loader_updater_), service_worker_route_id_); + std::move(pending_subresource_loader_updater_), service_worker_route_id_, + cors_exempt_header_list_); } void ServiceWorkerContextClient::OnNavigationPreloadResponse( diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h index 7d5dc2f5e57..f98e8214100 100644 --- a/chromium/content/renderer/service_worker/service_worker_context_client.h +++ b/chromium/content/renderer/service_worker/service_worker_context_client.h @@ -36,6 +36,8 @@ #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom-forward.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-forward.h" #include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom-forward.h" +#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-forward.h" +#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h" #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h" #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h" @@ -110,7 +112,8 @@ class CONTENT_EXPORT ServiceWorkerContextClient subresource_loader_updater, const GURL& script_url_to_skip_throttling, scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, - int32_t service_worker_route_id); + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list); // Called on the initiator thread. ~ServiceWorkerContextClient() override; @@ -119,17 +122,22 @@ class CONTENT_EXPORT ServiceWorkerContextClient std::unique_ptr<blink::WebEmbeddedWorker> worker, std::unique_ptr<blink::WebEmbeddedWorkerStartData> start_data, std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManagerParams>, - mojo::ScopedMessagePipeHandle content_settings_handle, - mojo::ScopedMessagePipeHandle cache_storage, - mojo::ScopedMessagePipeHandle browser_interface_broker); + mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy> + content_settings, + mojo::PendingRemote<blink::mojom::CacheStorage> cache_storage, + mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> + browser_interface_broker); // Called on the initiator thread. blink::WebEmbeddedWorker& worker(); // WebServiceWorkerContextClient overrides. void WorkerReadyForInspectionOnInitiatorThread( - mojo::ScopedMessagePipeHandle devtools_agent_ptr_info, - mojo::ScopedMessagePipeHandle devtools_agent_host_request) override; + blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + blink::CrossVariantMojoReceiver< + blink::mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) override; void FailedToFetchClassicScript() override; void FailedToFetchModuleScript() override; void WorkerScriptLoadedOnWorkerThread() override; @@ -239,7 +247,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient instance_host_; // This holds blink.mojom.ServiceWorkerContainer(Host) connections to the - // browser-side ServiceWorkerProviderHost to keep it alive there. + // browser-side ServiceWorkerHost to keep it alive there. // Note: |service_worker_provider_info_->script_loader_factory_remote| is // moved to WebServiceWorkerNetworkProviderImpl when // CreateServiceWorkerNetworkProvider is called. @@ -279,6 +287,8 @@ class CONTENT_EXPORT ServiceWorkerContextClient int32_t service_worker_route_id_; + std::vector<std::string> cors_exempt_header_list_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient); }; diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc index 930a79063be..b6dc30a5041 100644 --- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc +++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc @@ -36,7 +36,8 @@ ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl( preference_watcher_receiver, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater, - int32_t service_worker_route_id) + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list) : renderer_preferences_(renderer_preferences), worker_script_url_(worker_script_url), pending_url_loader_factory_(std::move(pending_url_loader_factory)), @@ -49,7 +50,8 @@ ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl( std::move(preference_watcher_receiver)), pending_subresource_loader_updater_( std::move(pending_subresource_loader_updater)), - service_worker_route_id_(service_worker_route_id) {} + service_worker_route_id_(service_worker_route_id), + cors_exempt_header_list_(cors_exempt_header_list) {} ServiceWorkerFetchContextImpl::~ServiceWorkerFetchContextImpl() {} @@ -62,6 +64,7 @@ void ServiceWorkerFetchContextImpl::SetTerminateSyncLoadEvent( void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread( blink::AcceptLanguagesWatcher* watcher) { resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); + resource_dispatcher_->SetCorsExemptHeaderList(cors_exempt_header_list_); resource_dispatcher_->set_terminate_sync_load_event( terminate_sync_load_event_); preference_watcher_receiver_.Bind( @@ -97,13 +100,12 @@ ServiceWorkerFetchContextImpl::GetURLLoaderFactory() { std::unique_ptr<blink::WebURLLoaderFactory> ServiceWorkerFetchContextImpl::WrapURLLoaderFactory( - mojo::ScopedMessagePipeHandle url_loader_factory_handle) { + blink::CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase> + url_loader_factory) { return std::make_unique<WebURLLoaderFactoryImpl>( resource_dispatcher_->GetWeakPtr(), base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( - mojo::PendingRemote<network::mojom::URLLoaderFactory>( - std::move(url_loader_factory_handle), - network::mojom::URLLoaderFactory::Version_))); + std::move(url_loader_factory))); } blink::WebURLLoaderFactory* @@ -202,7 +204,8 @@ blink::WebString ServiceWorkerFetchContextImpl::GetAcceptLanguages() const { return blink::WebString::FromUTF8(renderer_preferences_.accept_languages); } -mojo::ScopedMessagePipeHandle +blink::CrossVariantMojoReceiver< + blink::mojom::WorkerTimingContainerInterfaceBase> ServiceWorkerFetchContextImpl::TakePendingWorkerTimingReceiver(int request_id) { // No receiver exists because requests from service workers are never handled // by a service worker. diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h index 24a4c220089..d7f7634c330 100644 --- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h +++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h @@ -52,14 +52,17 @@ class CONTENT_EXPORT ServiceWorkerFetchContextImpl final preference_watcher_receiver, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater, - int32_t service_worker_route_id); + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list); // blink::WebServiceWorkerFetchContext implementation: void SetTerminateSyncLoadEvent(base::WaitableEvent*) override; void InitializeOnWorkerThread(blink::AcceptLanguagesWatcher*) override; blink::WebURLLoaderFactory* GetURLLoaderFactory() override; std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory( - mojo::ScopedMessagePipeHandle url_loader_factory_handle) override; + blink::CrossVariantMojoRemote< + network::mojom::URLLoaderFactoryInterfaceBase> url_loader_factory) + override; blink::WebURLLoaderFactory* GetScriptLoaderFactory() override; void WillSendRequest(blink::WebURLRequest&) override; blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode() @@ -70,8 +73,9 @@ class CONTENT_EXPORT ServiceWorkerFetchContextImpl final CreateWebSocketHandshakeThrottle( scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; blink::WebString GetAcceptLanguages() const override; - mojo::ScopedMessagePipeHandle TakePendingWorkerTimingReceiver( - int request_id) override; + blink::CrossVariantMojoReceiver< + blink::mojom::WorkerTimingContainerInterfaceBase> + TakePendingWorkerTimingReceiver(int request_id) override; void SetIsOfflineMode(bool) override; blink::mojom::SubresourceLoaderUpdater* GetSubresourceLoaderUpdater() override; @@ -136,6 +140,7 @@ class CONTENT_EXPORT ServiceWorkerFetchContextImpl final blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr; int32_t service_worker_route_id_; + std::vector<std::string> cors_exempt_header_list_; bool is_offline_mode_ = false; }; diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc index 236fbcdead3..3bedd8a075c 100644 --- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc +++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc @@ -48,7 +48,8 @@ TEST_F(ServiceWorkerFetchContextImplTest, SkipThrottling) { std::make_unique<FakeURLLoaderThrottleProvider>(), /*websocket_handshake_throttle_provider=*/nullptr, mojo::NullReceiver(), mojo::NullReceiver(), - /*service_worker_route_id=*/-1); + /*service_worker_route_id=*/-1, + /*cors_exempt_header_list=*/std::vector<std::string>()); { // Call WillSendRequest() for kScriptURL. diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.cc b/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.cc index 3a105adba2f..cc1f91ef808 100644 --- a/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.cc +++ b/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.cc @@ -62,17 +62,17 @@ class ServiceWorkerNetworkProviderForFrame::NewDocumentObserver std::unique_ptr<ServiceWorkerNetworkProviderForFrame> ServiceWorkerNetworkProviderForFrame::Create( RenderFrameImpl* frame, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) { - DCHECK(provider_info); + DCHECK(container_info); auto provider = base::WrapUnique(new ServiceWorkerNetworkProviderForFrame(frame)); provider->context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, - std::move(provider_info->client_receiver), - std::move(provider_info->host_remote), std::move(controller_info), + std::move(container_info->client_receiver), + std::move(container_info->host_remote), std::move(controller_info), std::move(fallback_loader_factory)); return provider; @@ -175,14 +175,13 @@ void ServiceWorkerNetworkProviderForFrame::DispatchNetworkQuiet() { context()->DispatchNetworkQuiet(); } -mojo::ScopedMessagePipeHandle +blink::CrossVariantMojoReceiver< + blink::mojom::WorkerTimingContainerInterfaceBase> ServiceWorkerNetworkProviderForFrame::TakePendingWorkerTimingReceiver( int request_id) { if (!context()) return {}; - auto worker_timing_receiver = - context()->TakePendingWorkerTimingReceiver(request_id); - return worker_timing_receiver.PassPipe(); + return context()->TakePendingWorkerTimingReceiver(request_id); } void ServiceWorkerNetworkProviderForFrame::NotifyExecutionReady() { diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.h b/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.h index d70fe501123..81624c1b8d8 100644 --- a/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.h +++ b/chromium/content/renderer/service_worker/service_worker_network_provider_for_frame.h @@ -31,7 +31,7 @@ class CONTENT_EXPORT ServiceWorkerNetworkProviderForFrame final // the loading context, e.g. a frame, provides it. static std::unique_ptr<ServiceWorkerNetworkProviderForFrame> Create( RenderFrameImpl* frame, - blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory); @@ -52,8 +52,9 @@ class CONTENT_EXPORT ServiceWorkerNetworkProviderForFrame final override; int64_t ControllerServiceWorkerID() override; void DispatchNetworkQuiet() override; - mojo::ScopedMessagePipeHandle TakePendingWorkerTimingReceiver( - int request_id) override; + blink::CrossVariantMojoReceiver< + blink::mojom::WorkerTimingContainerInterfaceBase> + TakePendingWorkerTimingReceiver(int request_id) override; ServiceWorkerProviderContext* context() { return context_.get(); } diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context.h b/chromium/content/renderer/service_worker/service_worker_provider_context.h index b0bac601dbf..79fc21d5d15 100644 --- a/chromium/content/renderer/service_worker/service_worker_provider_context.h +++ b/chromium/content/renderer/service_worker/service_worker_provider_context.h @@ -80,7 +80,7 @@ class CONTENT_EXPORT ServiceWorkerProviderContext public blink::mojom::ServiceWorkerContainer, public blink::mojom::ServiceWorkerWorkerClientRegistry { public: - // |receiver_| is connected to the content::ServiceWorkerProviderHost that + // |receiver| is connected to the content::ServiceWorkerContainerHost that // notifies of changes to the registration's and workers' status. // // |controller_info| contains the endpoint and object info that is needed to @@ -155,11 +155,11 @@ class CONTENT_EXPORT ServiceWorkerProviderContext CloneRemoteContainerHost(); // Called when WebServiceWorkerNetworkProvider is destructed. This function - // severs the Mojo binding to the browser-side ServiceWorkerProviderHost. The + // severs the Mojo binding to the browser-side ServiceWorkerContainerHost. The // reason WebServiceWorkerNetworkProvider is special compared to the other // providers, is that it is destructed synchronously when a service worker // client (Document) is removed from the DOM. Once this happens, the - // ServiceWorkerProviderHost must destruct quickly in order to remove the + // ServiceWorkerContainerHost must destruct quickly in order to remove the // ServiceWorkerClient from the system (thus allowing unregistration/update to // occur and ensuring the Clients API doesn't return the client). // @@ -167,9 +167,7 @@ class CONTENT_EXPORT ServiceWorkerProviderContext // state. void OnNetworkProviderDestroyed(); - // Gets the blink::mojom::ServiceWorkerContainerHost* for sending requests to - // browser-side ServiceWorkerProviderHost. May be nullptr if - // OnNetworkProviderDestroyed() has already been called. + // May be nullptr if OnNetworkProviderDestroyed() has already been called. // Currently this can be called only for clients that are Documents, // see comments of |container_host_|. blink::mojom::ServiceWorkerContainerHost* container_host() const; @@ -237,12 +235,12 @@ class CONTENT_EXPORT ServiceWorkerProviderContext const blink::mojom::ServiceWorkerContainerType container_type_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - // This keeps the connection to the content::ServiceWorkerProviderHost in the + // This keeps the connection to the content::ServiceWorkerContainerHost in the // browser process alive. mojo::AssociatedReceiver<blink::mojom::ServiceWorkerContainer> receiver_; // The |container_host_| remote represents the connection to the - // browser-side ServiceWorkerProviderHost, whose lifetime is bound to + // browser-side ServiceWorkerContainerHost, whose lifetime is bound to // |container_host_| via the Mojo connection. This may be nullptr if the Mojo // connection was broken in OnNetworkProviderDestroyed(). // diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc index 59b2ded1431..dadffb46dc7 100644 --- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc +++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc @@ -480,6 +480,10 @@ void ServiceWorkerSubresourceLoader::UpdateResponseTiming( // dispatching the fetch event, so set it to |dispatch_event_time|. response_head_->load_timing.service_worker_ready_time = timing->dispatch_event_time; + response_head_->load_timing.service_worker_fetch_start = + timing->dispatch_event_time; + response_head_->load_timing.service_worker_respond_with_settled = + timing->respond_with_settled_time; fetch_event_timing_ = std::move(timing); } @@ -566,10 +570,9 @@ void ServiceWorkerSubresourceLoader::StartResponse( // Read side data if necessary. We only do this if both the // |side_data_blob| is available to read and the request is destined // for a script. - auto resource_type = - static_cast<blink::mojom::ResourceType>(resource_request_.resource_type); + auto request_destination = resource_request_.destination; if (response->side_data_blob && - resource_type == blink::mojom::ResourceType::kScript) { + request_destination == network::mojom::RequestDestination::kScript) { side_data_as_blob_.Bind(std::move(response->side_data_blob->blob)); side_data_as_blob_->ReadSideData(base::BindOnce( &ServiceWorkerSubresourceLoader::OnSideDataReadingComplete, diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc index 2d4094787b7..d57c51b2425 100644 --- a/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc +++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc @@ -97,12 +97,16 @@ class FakeControllerServiceWorker static blink::mojom::FetchAPIResponsePtr OkResponse( blink::mojom::SerializedBlobPtr blob_body, - network::mojom::FetchResponseSource response_source) { + network::mojom::FetchResponseSource response_source, + base::Time response_time, + std::string cache_storage_cache_name) { auto response = blink::mojom::FetchAPIResponse::New(); response->status_code = 200; response->status_text = "OK"; response->response_type = network::mojom::FetchResponseType::kDefault; response->response_source = response_source; + response->response_time = response_time; + response->cache_storage_cache_name = cache_storage_cache_name; response->blob = std::move(blob_body); if (response->blob) { response->headers.emplace("Content-Length", @@ -223,6 +227,12 @@ class FakeControllerServiceWorker response_source_ = source; } + void SetCacheStorageCacheName(std::string cache_name) { + cache_storage_cache_name_ = cache_name; + } + + void SetResponseTime(base::Time time) { response_time_ = time; } + // blink::mojom::ControllerServiceWorker: void DispatchFetchEventForSubresource( blink::mojom::DispatchFetchEventParamsPtr params, @@ -240,11 +250,13 @@ class FakeControllerServiceWorker auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New(); timing->dispatch_event_time = base::TimeTicks::Now(); + timing->respond_with_settled_time = base::TimeTicks::Now(); switch (response_mode_) { case ResponseMode::kDefault: response_callback->OnResponse( - OkResponse(nullptr /* blob_body */, response_source_), + OkResponse(nullptr /* blob_body */, response_source_, + response_time_, cache_storage_cache_name_), std::move(timing)); std::move(callback).Run( blink::mojom::ServiceWorkerEventStatus::COMPLETED); @@ -255,14 +267,16 @@ class FakeControllerServiceWorker break; case ResponseMode::kStream: response_callback->OnResponseStream( - OkResponse(nullptr /* blob_body */, response_source_), + OkResponse(nullptr /* blob_body */, response_source_, + response_time_, cache_storage_cache_name_), std::move(stream_handle_), std::move(timing)); std::move(callback).Run( blink::mojom::ServiceWorkerEventStatus::COMPLETED); break; case ResponseMode::kBlob: response_callback->OnResponse( - OkResponse(std::move(blob_body_), response_source_), + OkResponse(std::move(blob_body_), response_source_, response_time_, + cache_storage_cache_name_), std::move(timing)); std::move(callback).Run( blink::mojom::ServiceWorkerEventStatus::COMPLETED); @@ -294,7 +308,8 @@ class FakeControllerServiceWorker blob->blob.InitWithNewPipeAndPassReceiver()); // Respond with a 206 response. - auto response = OkResponse(std::move(blob), response_source_); + auto response = OkResponse(std::move(blob), response_source_, + response_time_, cache_storage_cache_name_); response->status_code = 206; response->headers.emplace( "Content-Range", base::StringPrintf("bytes %zu-%zu/%zu", start, end, @@ -381,6 +396,9 @@ class FakeControllerServiceWorker network::mojom::FetchResponseSource response_source_ = network::mojom::FetchResponseSource::kUnspecified; + std::string cache_storage_cache_name_; + base::Time response_time_; + DISALLOW_COPY_AND_ASSIGN(FakeControllerServiceWorker); }; @@ -460,7 +478,6 @@ network::mojom::URLResponseHeadPtr CreateResponseInfoFromServiceWorker() { head->was_fallback_required_by_service_worker = false; head->url_list_via_service_worker = std::vector<GURL>(); head->response_type = network::mojom::FetchResponseType::kDefault; - head->is_in_cache_storage = false; head->cache_storage_cache_name = std::string(); head->did_service_worker_navigation_preload = false; return head; @@ -537,23 +554,28 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test { EXPECT_EQ(expected_info.url_list_via_service_worker, info.url_list_via_service_worker); EXPECT_EQ(expected_info.response_type, info.response_type); - EXPECT_EQ(expected_info.is_in_cache_storage, info.is_in_cache_storage); EXPECT_EQ(expected_info.cache_storage_cache_name, info.cache_storage_cache_name); + EXPECT_EQ(expected_info.response_time, info.response_time); + EXPECT_EQ(expected_info.service_worker_response_source, + info.service_worker_response_source); EXPECT_EQ(expected_info.did_service_worker_navigation_preload, info.did_service_worker_navigation_preload); EXPECT_NE(expected_info.load_timing.service_worker_start_time, info.load_timing.service_worker_start_time); EXPECT_NE(expected_info.load_timing.service_worker_ready_time, info.load_timing.service_worker_ready_time); + EXPECT_NE(expected_info.load_timing.service_worker_fetch_start, + info.load_timing.service_worker_fetch_start); + EXPECT_NE(expected_info.load_timing.service_worker_respond_with_settled, + info.load_timing.service_worker_respond_with_settled); } network::ResourceRequest CreateRequest(const GURL& url) { network::ResourceRequest request; request.url = url; request.method = "GET"; - request.resource_type = - static_cast<int>(blink::mojom::ResourceType::kSubResource); + request.destination = network::mojom::RequestDestination::kEmpty; return request; } @@ -601,8 +623,7 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test { CreateSubresourceLoaderFactory(); network::ResourceRequest request = CreateRequest(GURL("https://www.example.com/big-file")); - request.resource_type = - static_cast<int>(blink::mojom::ResourceType::kMedia); + request.destination = network::mojom::RequestDestination::kVideo; request.headers.SetHeader("Range", range_header); mojo::Remote<network::mojom::URLLoader> loader; std::unique_ptr<network::TestURLLoaderClient> client; @@ -917,7 +938,10 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse) { client->RunUntilResponseReceived(); auto& info = client->response_head(); - ExpectResponseInfo(*info, *CreateResponseInfoFromServiceWorker()); + auto expected_info = CreateResponseInfoFromServiceWorker(); + expected_info->service_worker_response_source = + network::mojom::FetchResponseSource::kNetwork; + ExpectResponseInfo(*info, *expected_info); // Write the body stream. uint32_t written_bytes = sizeof(kResponseBody) - 1; @@ -1019,6 +1043,10 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) { fake_controller_.RespondWithBlob(kMetadata, kResponseBody); fake_controller_.SetResponseSource( network::mojom::FetchResponseSource::kCacheStorage); + std::string cache_name = "v2"; + fake_controller_.SetCacheStorageCacheName(cache_name); + base::Time response_time = base::Time::Now(); + fake_controller_.SetResponseTime(response_time); mojo::Remote<network::mojom::URLLoaderFactory> factory = CreateSubresourceLoaderFactory(); @@ -1026,17 +1054,18 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) { // Perform the request. network::ResourceRequest request = CreateRequest(GURL("https://www.example.com/foo.js")); - request.resource_type = static_cast<int>(blink::mojom::ResourceType::kScript); + request.destination = network::mojom::RequestDestination::kScript; mojo::Remote<network::mojom::URLLoader> loader; std::unique_ptr<network::TestURLLoaderClient> client; StartRequest(factory, request, &loader, &client); client->RunUntilResponseReceived(); auto expected_info = CreateResponseInfoFromServiceWorker(); - // |is_in_cache_storage| should be true because |fake_controller_| sets the - // response source as CacheStorage. - expected_info->is_in_cache_storage = true; auto& info = client->response_head(); + expected_info->response_time = response_time; + expected_info->cache_storage_cache_name = cache_name; + expected_info->service_worker_response_source = + network::mojom::FetchResponseSource::kCacheStorage; ExpectResponseInfo(*info, *expected_info); EXPECT_EQ(39, info->content_length); @@ -1083,7 +1112,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) { // Perform the request. network::ResourceRequest request = CreateRequest(GURL("https://www.example.com/foo.js")); - request.resource_type = static_cast<int>(blink::mojom::ResourceType::kScript); + request.destination = network::mojom::RequestDestination::kScript; mojo::Remote<network::mojom::URLLoader> loader; std::unique_ptr<network::TestURLLoaderClient> client; StartRequest(factory, request, &loader, &client); @@ -1130,18 +1159,16 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseNonScript) { // Perform the request. network::ResourceRequest request = CreateRequest(GURL("https://www.example.com/foo.txt")); - request.resource_type = - static_cast<int>(blink::mojom::ResourceType::kSubResource); + request.destination = network::mojom::RequestDestination::kEmpty; mojo::Remote<network::mojom::URLLoader> loader; std::unique_ptr<network::TestURLLoaderClient> client; StartRequest(factory, request, &loader, &client); client->RunUntilResponseReceived(); - auto expected_info = CreateResponseInfoFromServiceWorker(); - // |is_in_cache_storage| should be true because |fake_controller_| sets the - // response source as CacheStorage. - expected_info->is_in_cache_storage = true; auto& info = client->response_head(); + auto expected_info = CreateResponseInfoFromServiceWorker(); + expected_info->service_worker_response_source = + network::mojom::FetchResponseSource::kCacheStorage; ExpectResponseInfo(*info, *expected_info); EXPECT_EQ(33, info->content_length); diff --git a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc index b1f3087729c..55441bc85c4 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc +++ b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc @@ -312,8 +312,8 @@ void WebServiceWorkerProviderImpl::OnDidGetRegistrationForReady( // GetRegistrationForReady() needs to respond some non-sense params even if it // has found that the request is a bad message and has called // mojo::ReportBadMessage(), this is forced by Mojo, please see - // content::ServiceWorkerProviderHost::GetRegistrationForReady(). We'll find a - // better solution once the discussion at + // content::ServiceWorkerContainerHost::GetRegistrationForReady(). We'll find + // a better solution once the discussion at // https://groups.google.com/a/chromium.org/forum/#!topic/chromium-mojo/NNsogKNurlA // settled. CHECK(registration); diff --git a/chromium/content/renderer/text_input_client_observer.cc b/chromium/content/renderer/text_input_client_observer.cc index e0129cefaf3..e91b05cbd20 100644 --- a/chromium/content/renderer/text_input_client_observer.cc +++ b/chromium/content/renderer/text_input_client_observer.cc @@ -8,6 +8,7 @@ #include <memory> +#include "content/common/mac/attributed_string_type_converters.h" #include "content/common/text_input_client_messages.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" @@ -67,10 +68,10 @@ void TextInputClientObserver::OnStringAtPoint(gfx::Point point) { baseline_point); } - std::unique_ptr<const mac::AttributedStringCoder::EncodedString> encoded( - mac::AttributedStringCoder::Encode(string)); + ui::mojom::AttributedStringPtr attributed_string = + ui::mojom::AttributedString::From(string); Send(new TextInputClientReplyMsg_GotStringAtPoint( - MSG_ROUTING_NONE, *encoded.get(), baseline_point)); + MSG_ROUTING_NONE, *attributed_string, baseline_point)); } void TextInputClientObserver::OnStringForRange(gfx::Range range) { @@ -83,10 +84,10 @@ void TextInputClientObserver::OnStringForRange(gfx::Range range) { string = blink::WebSubstringUtil::AttributedSubstringInRange( frame, range.start(), range.length(), &baseline_point); } - std::unique_ptr<const mac::AttributedStringCoder::EncodedString> encoded( - mac::AttributedStringCoder::Encode(string)); + ui::mojom::AttributedStringPtr attributed_string = + ui::mojom::AttributedString::From(string); Send(new TextInputClientReplyMsg_GotStringForRange( - MSG_ROUTING_NONE, *encoded.get(), baseline_point)); + MSG_ROUTING_NONE, *attributed_string, baseline_point)); } } // namespace content diff --git a/chromium/content/renderer/theme_helper_mac.h b/chromium/content/renderer/theme_helper_mac.h index 98e6949143a..9b4feecbf15 100644 --- a/chromium/content/renderer/theme_helper_mac.h +++ b/chromium/content/renderer/theme_helper_mac.h @@ -15,6 +15,10 @@ void SystemColorsDidChange(int aqua_color_variant, const std::string& highlight_text_color, const std::string& highlight_color); +// MacOS 10.14 (Mojave) disabled subpixel anti-aliasing by default, but this can +// be overridden with a setting (CGFontRenderingFontSmoothingDisabled). +bool IsSubpixelAntialiasingAvailable(); + } // namespace content #endif // CONTENT_RENDERER_THEME_HELPER_MAC_H_ diff --git a/chromium/content/renderer/theme_helper_mac.mm b/chromium/content/renderer/theme_helper_mac.mm index 7fbc6ba1a55..1db12974099 100644 --- a/chromium/content/renderer/theme_helper_mac.mm +++ b/chromium/content/renderer/theme_helper_mac.mm @@ -8,6 +8,10 @@ #include "base/strings/sys_string_conversions.h" +extern "C" { +bool CGFontRenderingGetFontSmoothingDisabled(void) API_AVAILABLE(macos(10.14)); +} + namespace content { void SystemColorsDidChange(int aqua_color_variant, @@ -52,4 +56,12 @@ void SystemColorsDidChange(int aqua_color_variant, object:nil]; } +bool IsSubpixelAntialiasingAvailable() { + if (__builtin_available(macOS 10.14, *)) { + // See https://trac.webkit.org/changeset/239306/webkit for more info. + return !CGFontRenderingGetFontSmoothingDisabled(); + } + return true; +} + } // namespace content diff --git a/chromium/content/renderer/worker/dedicated_worker_host_factory_client.cc b/chromium/content/renderer/worker/dedicated_worker_host_factory_client.cc index d7cd765d88d..d692977de5e 100644 --- a/chromium/content/renderer/worker/dedicated_worker_host_factory_client.cc +++ b/chromium/content/renderer/worker/dedicated_worker_host_factory_client.cc @@ -7,7 +7,9 @@ #include <utility> #include "content/renderer/loader/child_url_loader_factory_bundle.h" #include "content/renderer/loader/navigation_response_override_parameters.h" +#include "content/renderer/loader/resource_dispatcher.h" #include "content/renderer/loader/web_worker_fetch_context_impl.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/service_worker_provider_context.h" #include "content/renderer/worker/fetch_client_settings_object_helpers.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -39,7 +41,7 @@ void DedicatedWorkerHostFactoryClient::CreateWorkerHostDeprecated( browser_interface_broker; factory_->CreateWorkerHost( browser_interface_broker.InitWithNewPipeAndPassReceiver(), - remote_host_.BindNewPipeAndPassReceiver(), std::move(callback)); + std::move(callback)); OnWorkerHostCreated(std::move(browser_interface_broker)); } @@ -47,16 +49,14 @@ void DedicatedWorkerHostFactoryClient::CreateWorkerHost( const blink::WebURL& script_url, network::mojom::CredentialsMode credentials_mode, const blink::WebFetchClientSettingsObject& fetch_client_settings_object, - mojo::ScopedMessagePipeHandle blob_url_token) { + blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase> + blob_url_token) { DCHECK(base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)); factory_->CreateWorkerHostAndStartScriptLoad( script_url, credentials_mode, FetchClientSettingsObjectFromWebToMojom(fetch_client_settings_object), - mojo::PendingRemote<blink::mojom::BlobURLToken>( - std::move(blob_url_token), blink::mojom::BlobURLToken::Version_), - receiver_.BindNewPipeAndPassRemote(), - remote_host_.BindNewPipeAndPassReceiver()); + std::move(blob_url_token), receiver_.BindNewPipeAndPassRemote()); } scoped_refptr<blink::WebWorkerFetchContext> @@ -84,12 +84,6 @@ DedicatedWorkerHostFactoryClient::CloneWorkerFetchContext( return worker_fetch_context; } -void DedicatedWorkerHostFactoryClient::LifecycleStateChanged( - blink::mojom::FrameLifecycleState state) { - if (remote_host_) - remote_host_->LifecycleStateChanged(state); -} - scoped_refptr<WebWorkerFetchContextImpl> DedicatedWorkerHostFactoryClient::CreateWorkerFetchContext( blink::mojom::RendererPreferences renderer_preference, @@ -103,7 +97,10 @@ DedicatedWorkerHostFactoryClient::CreateWorkerFetchContext( std::move(renderer_preference), std::move(watcher_receiver), subresource_loader_factory_bundle_->Clone(), subresource_loader_factory_bundle_->CloneWithoutAppCacheFactory(), - std::move(pending_subresource_loader_updater_)); + std::move(pending_subresource_loader_updater_), + RenderThreadImpl::current() + ->resource_dispatcher() + ->cors_exempt_header_list()); worker_fetch_context->SetResponseOverrideForMainScript( std::move(response_override_for_main_script_)); return worker_fetch_context; @@ -112,12 +109,12 @@ DedicatedWorkerHostFactoryClient::CreateWorkerFetchContext( void DedicatedWorkerHostFactoryClient::OnWorkerHostCreated( mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker) { - worker_->OnWorkerHostCreated(browser_interface_broker.PassPipe()); + worker_->OnWorkerHostCreated(std::move(browser_interface_broker)); } void DedicatedWorkerHostFactoryClient::OnScriptLoadStarted( - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr + service_worker_container_info, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> pending_subresource_loader_factory_bundle, @@ -139,12 +136,12 @@ void DedicatedWorkerHostFactoryClient::OnScriptLoadStarted( pending_subresource_loader_updater_ = std::move(subresource_loader_updater); DCHECK(!service_worker_provider_context_); - if (service_worker_provider_info) { + if (service_worker_container_info) { service_worker_provider_context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForDedicatedWorker, - std::move(service_worker_provider_info->client_receiver), - std::move(service_worker_provider_info->host_remote), + std::move(service_worker_container_info->client_receiver), + std::move(service_worker_container_info->host_remote), std::move(controller_info), subresource_loader_factory_bundle_); } diff --git a/chromium/content/renderer/worker/dedicated_worker_host_factory_client.h b/chromium/content/renderer/worker/dedicated_worker_host_factory_client.h index c7ecbbc4ac5..bb075902678 100644 --- a/chromium/content/renderer/worker/dedicated_worker_host_factory_client.h +++ b/chromium/content/renderer/worker/dedicated_worker_host_factory_client.h @@ -12,7 +12,6 @@ #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom-forward.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom-forward.h" -#include "third_party/blink/public/mojom/worker/dedicated_worker_host.mojom.h" #include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h" #include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h" @@ -50,11 +49,11 @@ class DedicatedWorkerHostFactoryClient final const blink::WebURL& script_url, network::mojom::CredentialsMode credentials_mode, const blink::WebFetchClientSettingsObject& fetch_client_settings_object, - mojo::ScopedMessagePipeHandle blob_url_token) override; + blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase> + blob_url_token) override; scoped_refptr<blink::WebWorkerFetchContext> CloneWorkerFetchContext( blink::WebWorkerFetchContext* web_worker_fetch_context, scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; - void LifecycleStateChanged(blink::mojom::FrameLifecycleState state) override; scoped_refptr<WebWorkerFetchContextImpl> CreateWorkerFetchContext( blink::mojom::RendererPreferences renderer_preference, @@ -67,8 +66,8 @@ class DedicatedWorkerHostFactoryClient final mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker) override; void OnScriptLoadStarted( - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr + service_worker_container_info, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> pending_subresource_loader_factory_bundle, @@ -91,7 +90,6 @@ class DedicatedWorkerHostFactoryClient final mojo::Remote<blink::mojom::DedicatedWorkerHostFactory> factory_; mojo::Receiver<blink::mojom::DedicatedWorkerHostFactoryClient> receiver_{ this}; - mojo::Remote<blink::mojom::DedicatedWorkerHost> remote_host_; }; } // namespace content diff --git a/chromium/content/renderer/worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/worker/embedded_shared_worker_stub.cc index 66c5f9877cb..1b51772529e 100644 --- a/chromium/content/renderer/worker/embedded_shared_worker_stub.cc +++ b/chromium/content/renderer/worker/embedded_shared_worker_stub.cc @@ -19,8 +19,10 @@ #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" #include "third_party/blink/public/common/messaging/message_port_descriptor.h" +#include "third_party/blink/public/mojom/browser_interface_broker.mojom.h" #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" +#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h" #include "third_party/blink/public/platform/web_fetch_client_settings_object.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/web/web_shared_worker.h" @@ -40,8 +42,8 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( preference_watcher_receiver, mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy> content_settings, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr + service_worker_container_info, const base::UnguessableToken& appcache_host_id, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> @@ -50,12 +52,14 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( mojo::PendingRemote<blink::mojom::SharedWorkerHost> host, mojo::PendingReceiver<blink::mojom::SharedWorker> receiver, mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> - browser_interface_broker) + browser_interface_broker, + const std::vector<std::string>& cors_exempt_header_list) : receiver_(this, std::move(receiver)), host_(std::move(host)), url_(info->url), renderer_preferences_(renderer_preferences), - preference_watcher_receiver_(std::move(preference_watcher_receiver)) { + preference_watcher_receiver_(std::move(preference_watcher_receiver)), + cors_exempt_header_list_(cors_exempt_header_list) { DCHECK(main_script_load_params); DCHECK(pending_subresource_loader_factory_bundle); @@ -93,12 +97,12 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( std::make_unique<ChildPendingURLLoaderFactoryBundle>( std::move(pending_subresource_loader_factory_bundle))); - if (service_worker_provider_info) { + if (service_worker_container_info) { service_worker_provider_context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForDedicatedWorker, - std::move(service_worker_provider_info->client_receiver), - std::move(service_worker_provider_info->host_remote), + std::move(service_worker_container_info->client_receiver), + std::move(service_worker_container_info->host_remote), std::move(controller_info), subresource_loader_factory_bundle_); } @@ -112,8 +116,8 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( info->content_security_policy_type, info->creation_address_space, FetchClientSettingsObjectFromMojomToWeb( info->outside_fetch_client_settings_object), - appcache_host_id, devtools_worker_token, content_settings.PassPipe(), - browser_interface_broker.PassPipe(), pause_on_start); + appcache_host_id, devtools_worker_token, std::move(content_settings), + std::move(browser_interface_broker), pause_on_start); // If the host drops its connection, then self-destruct. receiver_.set_disconnect_handler(base::BindOnce( @@ -126,14 +130,13 @@ EmbeddedSharedWorkerStub::~EmbeddedSharedWorkerStub() { } void EmbeddedSharedWorkerStub::WorkerReadyForInspection( - mojo::ScopedMessagePipeHandle devtools_agent_remote_handle, - mojo::ScopedMessagePipeHandle devtools_agent_host_receiver_handle) { - mojo::PendingRemote<blink::mojom::DevToolsAgent> remote( - std::move(devtools_agent_remote_handle), - blink::mojom::DevToolsAgent::Version_); - mojo::PendingReceiver<blink::mojom::DevToolsAgentHost> receiver( - std::move(devtools_agent_host_receiver_handle)); - host_->OnReadyForInspection(std::move(remote), std::move(receiver)); + blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + blink::CrossVariantMojoReceiver< + blink::mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) { + host_->OnReadyForInspection(std::move(devtools_agent_remote), + std::move(devtools_agent_host_receiver)); } void EmbeddedSharedWorkerStub::WorkerScriptLoadFailed( @@ -178,7 +181,8 @@ EmbeddedSharedWorkerStub::CreateWorkerFetchContext() { std::move(preference_watcher_receiver_), subresource_loader_factory_bundle_->Clone(), std::move(fallback_factory), - /*pending_subresource_loader_updater*/ mojo::NullReceiver()); + /*pending_subresource_loader_updater*/ mojo::NullReceiver(), + cors_exempt_header_list_); // TODO(horo): To get the correct first_party_to_cookies for the shared // worker, we need to check the all documents bounded by the shared worker. diff --git a/chromium/content/renderer/worker/embedded_shared_worker_stub.h b/chromium/content/renderer/worker/embedded_shared_worker_stub.h index ee4cb15a962..8198b997015 100644 --- a/chromium/content/renderer/worker/embedded_shared_worker_stub.h +++ b/chromium/content/renderer/worker/embedded_shared_worker_stub.h @@ -68,8 +68,8 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, preference_watcher_receiver, mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy> content_settings, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr + service_worker_container_info, const base::UnguessableToken& appcache_host_id, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> @@ -78,7 +78,8 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, mojo::PendingRemote<blink::mojom::SharedWorkerHost> host, mojo::PendingReceiver<blink::mojom::SharedWorker> receiver, mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> - browser_interface_broker); + browser_interface_broker, + const std::vector<std::string>& cors_exempt_header_list); ~EmbeddedSharedWorkerStub() override; // blink::WebSharedWorkerClient implementation. @@ -86,8 +87,11 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, void WorkerContextClosed() override; void WorkerContextDestroyed() override; void WorkerReadyForInspection( - mojo::ScopedMessagePipeHandle devtools_agent_ptr_info, - mojo::ScopedMessagePipeHandle devtools_agent_host_request) override; + blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + blink::CrossVariantMojoReceiver< + blink::mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) override; void WorkerScriptLoadFailed(const std::string& error_message) override; void WorkerScriptEvaluated(bool success) override; scoped_refptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext() @@ -114,6 +118,8 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, preference_watcher_receiver_; std::unique_ptr<blink::WebSharedWorker> impl_; + std::vector<std::string> cors_exempt_header_list_; + using PendingChannel = std::pair<int /* connection_request_id */, blink::MessagePortChannel>; std::vector<PendingChannel> pending_channels_; diff --git a/chromium/content/renderer/worker/shared_worker_factory_impl.cc b/chromium/content/renderer/worker/shared_worker_factory_impl.cc index ce9e24b1a54..38c30ab355c 100644 --- a/chromium/content/renderer/worker/shared_worker_factory_impl.cc +++ b/chromium/content/renderer/worker/shared_worker_factory_impl.cc @@ -5,6 +5,8 @@ #include "content/renderer/worker/shared_worker_factory_impl.h" #include "base/memory/ptr_util.h" +#include "content/renderer/loader/resource_dispatcher.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/worker/embedded_shared_worker_stub.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" @@ -33,8 +35,8 @@ void SharedWorkerFactoryImpl::CreateSharedWorker( preference_watcher_receiver, mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy> content_settings, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr + service_worker_container_info, const base::Optional<base::UnguessableToken>& appcache_host_id, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> @@ -49,12 +51,14 @@ void SharedWorkerFactoryImpl::CreateSharedWorker( std::move(info), constructor_origin, user_agent, ua_metadata, pause_on_start, devtools_worker_token, *renderer_preferences, std::move(preference_watcher_receiver), std::move(content_settings), - std::move(service_worker_provider_info), + std::move(service_worker_container_info), appcache_host_id.value_or(base::UnguessableToken()), std::move(main_script_load_params), std::move(subresource_loader_factories), std::move(controller_info), - std::move(host), std::move(receiver), - std::move(browser_interface_broker)); + std::move(host), std::move(receiver), std::move(browser_interface_broker), + RenderThreadImpl::current() + ->resource_dispatcher() + ->cors_exempt_header_list()); } } // namespace content diff --git a/chromium/content/renderer/worker/shared_worker_factory_impl.h b/chromium/content/renderer/worker/shared_worker_factory_impl.h index 6b484f421e4..593e419fc94 100644 --- a/chromium/content/renderer/worker/shared_worker_factory_impl.h +++ b/chromium/content/renderer/worker/shared_worker_factory_impl.h @@ -38,8 +38,8 @@ class SharedWorkerFactoryImpl : public blink::mojom::SharedWorkerFactory { preference_watcher_receiver, mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy> content_settings, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, + blink::mojom::ServiceWorkerContainerInfoForClientPtr + service_worker_container_info, const base::Optional<base::UnguessableToken>& appcache_host_id, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> |